众所周知,Python是一门动态语言,在运行时,可以改变其结构,这既是Python的魅力所在,也是它容易踩坑的地方,所以一般大型项目多是用Java等静态语言编写
简单的举例来说,Python在定义一个对象时,不需要像Java那样在变量前面申明其定义,这是Python的方便快捷之处
我们创建一个类来简单说下其动态的表现形式
>>> class Person(object):
... def __init__(self, name, age):
... self.name = name
... self.age = age
... def eat(self):
... print('eat food')
...
>>> p = Person('Lee', 25)
>>> p.name
'Lee'
>>> p.age
25
>>> p.sex
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'sex'
这里发现我们是没有定义sex的,但我们可以给对象绑定属性
>>> p.sex = 'male'
>>> p.sex
'male'
如果我们重新定一个Person呢?
>>> p1 = Person('Bob', 25)
>>> p1.sex
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'sex'
>>> Person.sex = 'male'
>>> p1.sex
'male'
如上面的代码看,之前的sex是绑定在p对象上,所以p1无这个属性,但我们可以直接给类绑定属性,让p1也可以直接拥有
>>> p.eat()
eat food
>>> p.run()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'run'
因为没有在类中没有定义run这个函数,所以报错
>>> def run(self, speed):
... print('%s is running at the speed of %d m/s' % (self.name, speed))
...
>>>import types
>>> p.run = types.MethodType(run, p)
>>> p.run(10)
Lee is running at the speed of 10 m/s
我们可以给对象绑定方法,使其 “动态的”拥有,即使在定义时没有定义这个方法
同上,p1是没有这个run方法的,我们可以给类绑定方法
>>> p1.run()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'run'
>>> Person.run = run
>>> p1.run(10)
Bob is running at the speed of 10 m/s
除了绑定方法和属性,我们还可以删除方法和属性
>>> p2 = Person('Mike', 25)
>>> p2.name
'Mike'
>>> p2.age
25
>>> p2.run(5)
Mike is running at the speed of 5 m/s
>>> del p2.name
>>> delattr(p2, 'age')
>>> p2.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'name'
>>> p2.age
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'age'
>>> del Person.run
>>> p2.run(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'run'
如果我们想要限制实例的属性怎么办呢?比如只允许给Person定义name和age属性
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的
__slots __变量,来限制该class实例能添加的属性:
>>> class Person(object):
... __slots__ = ('name', 'age')
...
>>> p = Person()
>>> p.name = 'Lee'
>>> p.age = 25
>>> p.score = 100
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Person' object has no attribute 'score'
不过要注意的是,__slots __只对当前的类实例起作用,对子类实例不起作用:
>>> class Test(Person):
... pass
...
>>> t = Test()
>>> t.score = 100
>>> t.score
100
Summary | 小结
1、 给对象添加属性或方法
+ 属性: 对象.属性 = 属性值
+ 方法: def 方法...
import types
对象.方法 = types.MethodType(方法, 对象)
2、 给类添加属性或方法
+ 属性: 类.属性 = 属性值
+ 方法: def 方法...
类.方法 = 方法
3、 删除属性或方法
del 对象.属性
delattr(对象, ‘属性’)
del 类.方法
delattr(类, '方法')
4、 固定属性使用__slots __
class 类(object):
__slots__ : ('属性'...)
5、 __slots __只对当前的类实例起作用,对子类实例不起作用