鱼C论坛

 找回密码
 立即注册
查看: 1960|回复: 1

[学习笔记] 【第040讲心得】【使用@property和使用__slot__】

[复制链接]
发表于 2018-12-26 10:05:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 heidern0612 于 2018-12-26 19:49 编辑

写心得的过程都是自我思考的过程,借鉴了很多论坛前辈和互联网大佬的经验,仓促间难免出错,如有错误,恳请指出,感激不尽。


网上扒了一大堆关于@property的文章,算是有点小感悟,趁热打铁写下来。

(此文主要借鉴了廖雪峰大神blog中关于@property一章节:戳我前进)。

以及CSDN里关于@property的一篇文章:戳我前进




主要写几个自己认知过程中的重点:


1、@property的作用:


   A、将类方法转换为只读属性;

   B、重新实现一个属性的setter和getter方法;


2、@property的简单使用介绍:

如果在一个类中要设置和获取一个成员变量的话,正常的写法应该是以下这种经典的写法。
class Student(object):
    
    __slots__ = ('__name', '__age', '__score')
    
    def __init__(self, name, age, score = 0):
        self.__name = name
        self.__age = age
        self.__score = score
        
   
    def getscore(self):    # 获取score
        return self.__score
    
    
    def setscore(self, score):   # 设置score value
        if not isinstance(score, int):
            raise ValueError('Score必须是int类型!')
        if score < 0 or score > 100:
            raise ValueError('Score值必须在0=<score<=100')
        self.__score = score

在实际的应用过程中,如果要get/set score就得如下这种写法:
stu = Student('Wuli', 28)
stu.setscore(88)
stu.getscore() = 88

这样这样写本没有什么错, 但是鉴于在实际的码code的过程中,getfuncname/setfuncname实在是太普通了。

我们可能希望get/set一个值时有更简单的方法(如下),像设置成员变量一样去设置一个变量,又可以检查类型参数,如下:
#设置成员变量
stu.score = 100
#获取成员变量值
stu.score 
# 报错:
AttributeError    Traceback (most recent call last)
<ipython-input-9-fb8376649a7b> in <module>()
----> 1 stu.__score = 88
AttributeError: 'Student' object has no attribute '__score'

还真可以,因了python有@property 装饰器。我们对前面的代码稍稍做一些修改。
class Student(object):
    
    __slots__ = ('__name', '__age', '__score')
    
    def __init__(self, name, age, score = 0):
        self.__name = name
        self.__age = age
        self.__score = score
        
    # 获取score
    @property
    def score(self):
        return self.__score
    
    # 设置score value
    @score.setter
    def score(self, score):
        if not isinstance(score, int):
            raise ValueError('Score必须是int类型!')
        if score < 0 or score > 100:
            raise ValueError('Score值必须在0=<score<=100')
        self.__score = score


注意一下第1段代码与第2段代码之间的差异, get/set的函数名都变成一样了。

但是上了分别多了一个@property/@score.setter.

@property 加了这个装饰器的funcname相当于getfuncname()

@score.setter 加了这个装饰器的funcname相当于setfuncname


自此,你就可以像耍成员变量一样的去耍它们了。
In [15]: stu = Student('wuli2', 28)
In [16]: stu.score = 88
In [17]: print(stu.score)
88


3、@property如何将类方法定义成只读?

如下,只定义getter方法,不定义setter方法就是一个只读属性:
class Student(object):

    @property
    def birth(self):

        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2015 - self._birth


这里的self.age实例化后属性就无法进行修改或设置。




                               
登录/注册后可看大图

                               
登录/注册后可看大图


上述关于介绍@property的代码中出现了:
__slots__ = ('__name', '__age', '__score')


这个__slot__是个什么意思呢?


slots的作用一:阻止在实例化类时为实例分配dict,节省内存空间。

python中新模式的class,即从object继承下来的类有一个变量是__slots__。

在默认情况下每个类都会有一个dict,通过__dict__访问,这个dict维护了这个实例的所有属性,

例如:
class Base(object):
    v = 1
    def __init__(self):
          pass

b = Base()
print (b.__dict__)

b.x = 2
print (b.__dict__)

可见:实例的dict只保持实例的变量,对于类的属性是不保存的,类的属性包括变量和函数。

由于每次实例化一个类都要分配一个新的dict,因此存在空间的浪费,因此有了slots。

当定义了slots后,slots中定义的变量变成了类的描述符,类的实例只能拥有这些个变量,而不在有dict,因此也就不能在增加新的变量。

如果你实在不能理解上面一大坨,你可以简单的理解为:当类被大量实例化的时候,__slot__可以不为实例化分配字典,节省了内存空间。



slots的作用二:限制该class能添加的属性。
class Student(object): 
      __slots__ = ('name', 'age')    # 用tuple定义允许绑定的属性名称
      

s= Student ()

s.name = "John"
s.age = 30
s.score = 35

如以上代码,如果不添加最后一句s.score = 35,代码是可以正常运行的。

但如果添加了最后一句,就会抛出个AttributeError的错误,提示你Student类没有score属性。



另外,需要注意的是,,__slots__定义的属性仅对当前类起作用,对继承的子类是不起作用的。

除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__。


如下代码运行是没有错误的。
class StudentA(object): 
      __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称


class StudentB(StudentA): 
      __slots__ = ('score') 
  
  
      
s= StudentB ()

s.name = "海顿上校"
s.age = 30
s.score = 35




本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-4-20 22:26:46 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 08:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表