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
一般我们的repr跟str内容是一样的 ,我们可以这样写
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
是不是很有意思
后续更新