Python中类的特殊属性和方法

2016-10-11  本文已影响882人  Rokkia

1. 特殊属性

所有名称类似__xxx__的属性和方法名都要小心
在python中有特殊用途,也被成为魔法方法。
1.1__slots__
__slots__ ,因为简书格式问题,这样写会变成字体加粗。
后面简称slots,在实例中还是会用__slots__的。

先说下slots的作用,slots的作用是规定类中的属性。
直接来个例子:

#创建一个简单的类来看看  
class Student(object):
    def __init__(self):
        pass
#使用看看
s1 = Student()   
s1.score = 100
s1.score
#在不加__slots__的时候没有任何问题

同样的代码 加上slots试试

class Student(object):
    #在这里我们设置一个__slots__ 
    #给这个类规定只允许创建两个属性
    #分别是name ,age 
    __slots__ = ('name','age')
    def __init__(self):
        pass
#使用看看
s1 = Student()   
s1.score = 100
#boom 这里会报一个不认识score属性的错误
AttributeError: 'Student' object has no attribute 'score'
就是因为我们在类中设置了,__slots__属性,所以我们不能给s1绑定score属性。

但是slots有很多的问题
第一个就是,他并不只针对实例绑定属性。
如:

class Student(object):
    #在这里我们设置一个__slots__ 
    #给这个类规定只允许创建两个属性
    #分别是name ,age 
    __slots__ = ('name','age')
    def __init__(self):
        pass
    def set_score(self,score):
        self.score = score

s1 = Student()
s1.set_score(100)
#boom  报错
AttributeError: 'Student' object has no attribute 'score'

即使你想在类里面给这个类添加属性也是不行的。

第二,这点我认为是比较坑的,使用slots,貌似就不能使用@property了
如:

class Student(object):
    #在这里我们设置一个__slots__ 
    #给这个类规定只允许创建两个属性
    #分别是name ,age 
    __slots__ = ('name','age')
    def __init__(self):
        pass
    #使用@property添加一个name属性
    @property 
    def name(self):
        return self._name
    @name.setter
    def name(self,value):
        self._name = value

s1 = Student()
s1.name = '1Ran'
#boom 报错,虽然我们在__slots中添加了name属性,但是在使用@property时,并没有办法识别_name
AttributeError: 'Student' object has no attribute '_name'

这里我也在网上找了找 ,貌似大家并没有这个问题。如果有已经解决的还望可以留言。

最后要说一下,slots并不针对子类
如:

class Student(object):
    #在这里我们设置一个__slots__ 
    #给这个类规定只允许创建两个属性
    #分别是name ,age 
    __slots__ = ('name','age')
    def __init__(self):
        pass
#创建女同学子类
class GirlStudent(Student):
    def __init__(self):
        pass
#创建一个女同学
gs1 = GirlStudent()
#给其绑定score,使用score,没有任何问题
gs1.score = 100
gs1.score
100

2.特殊方法

2.1__str__
全名__str__,这个方法可以让我们的实例打印的更加的漂亮。

#创建一个Teacher类
class Teacher(object):
    def __init__(self,name):
        self.__name = name

#创建t1
t1 = Teacher('1Ran')
#打印t1
print t1
<__main__.Teacher object at 0x103fab250>
十个人九个人看不懂这说的是什么
于是我们可以使用__str__方法来自定义
class Teacher(object):
    def __init__(self,name):
        self.__name = name
    def __str__(self):
        return 'Object is Teacher, name is %s' % (self.__name)
#创建
t1 = Teacher('1Ran')
#打印
print t1
Object is Teacher, name is 1Ran
这样大家应该就能看懂了 

但是当我们直接输出t1时 ,你会发现结果大概是这样的

t1
<__main__.Teacher at 0x103fa0dd0>

这时候就需要使用repr

2.2__repr__
__repr__ ,可以自定义你直接打印的格式

如:

class Teacher(object):
    def __init__(self,name):
        self.__name = name
    def __str__(self):
         return 'Object is Teacher ,name is %s' % (self.__name)
    def __repr__(self):
         return 'Object is Teacher ,name is %s ' % (self.__name)
#创建t1
t1 = Teacher('1Ran')
#打印结果
t1
Object is Teacher ,name is 1Ran

一般我们的reprstr内容是一样的 ,我们可以这样写

class Teacher(object):
    def __init__(self,name):
        self.__name = name
    def __str__(self):
         return 'Object is Teacher ,name is %s' % (self.__name)
    #直接相等就ok了 
    __repr__ = __str__

2.3__getattr__
__getattr__ 的使用主要是当你调用一个属性,但是这个属性实例中并没有时,为了不让报错,给予其一个默认值

如:

class Teacher(object):
    def  __init__(self):
        pass
#创建t1
t1 = Teacher()
#使用t1不存在的属性age
t1.age
#boom 报错 Teacher并没有age属性
AttributeError: 'Teacher' object has no attribute 'age'

如果不行让他不错,我们可以这样

class Teacher(object):
    def __init__(self):
        pass
    def __getattr__(self,attr):
        if attr == 'age':
            #18岁女老师 ,嘿嘿嘿
            return 18
#创建t1
t1 = Teacher()
#打印t1.age  
t1.age
#没有问题哦  18岁的女老师
18

是不是很有意思

后续更新

上一篇 下一篇

猜你喜欢

热点阅读