python是动态语言
1. 动态语言的定义
动态编程语言
是 高级程序设计语言
的一个类别,在计算机科学领域已被广泛应用。它是一类 在运行时可以改变其结构
的语言 :例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。动态语言目前非常具有活力。例如JavaScript便是一个动态语言,除此之外如 PHP 、 Ruby 、 Python 等也都属于动态语言,而 C 、 C++ 等语言则不属于动态语言。----来自 维基百科
2. 运行的过程中给类对象和实例对象绑定(添加)属性
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print('%s正在吃...' % self.name)
# 动态添加属性
p1 = Person('老一', 28)
p2 = Person('老二', 23)
Person.sex = 'man' # 给类添加类属性
p1.address = '广州' # 给p1实例对象添加属性,只能在该实例下访问
print(p1.address)
#print(p2.address) # p2实例对象没有添加属性,所以会报错 AttributeError: 'Person' object has no attribute 'address'
3. 运行的过程中给类对象和实例对象绑定(添加)方法
动态添加实例方法、类方法、静态方法
# 动态添加实例方法
def running(cls): # 第一个参数接收Person object
print(cls) # <__main__.Person object at 0x7f33db18bc18>
print('%s正在跑...' % cls.name)
Person.run = running # 实际上:让类属性Person.run指向了running函数的内存(Person.run = 函数的引用)
p1.run()
from types import MethodType
# 给实例对象添加实例方法需要用到types模块中的MethodType
p2.run = MethodType(running, p2)
p2.run()
# 动态添加类方法
@classmethod
def classFunction(cls):
print('classFunction')
# p1.class_fun = classFunction
# p1.class_fun() # 实例化对象不能添加类方法 TypeError: 'classmethod' object is not callable
Person.class_fun = classFunction
p1.class_fun()
# 动态添加静态方法
@staticmethod
def staticFunction():
print('staticFunction')
# p1.static_fun = staticFunction
# p1.static_fun() # 实例化对象不能添加静态方法 TypeError: 'staticmethod' object is not callable
Person.static_fun = staticFunction
p1.static_fun()
运行结果:
/home/longhui/Desktop/core_python_programming/venv/bin/python /home/longhui/Desktop/core_python_programming/venv/include/python_advanced_programming/part2/dynamic_add.py
广州
<__main__.Person object at 0x7f51037dec18>
老一正在跑...
<__main__.Person object at 0x7f51037def60>
老二正在跑...
classFunction
staticFunction
Process finished with exit code 0
4. 运行的过程中删除属性、方法
删除的方法:
- del 对象.属性名
- delattr(对象, "属性名")
# 删除属性
print(p1.sex)
# del Person.sex
delattr(Person, 'sex')
# print(p1.sex) # AttributeError: 'Person' object has no attribute 'sex'
通过以上例子可以得出一个结论:相对于动态语言,静态语言具有严谨性!所以,玩动态语言的时候,小心动态的坑!
那么怎么避免这种情况呢? 请使用__slots__
5.__slots__的作用
现在我们终于明白了,动态语言与静态语言的不同
动态语言:可以在运行的过程中,修改代码
静态语言:编译时已经确定好代码,运行过程中不能修改
如果我们想要限制实例的属性怎么办?比如,只允许对Person实例添加name和age属性。
为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
注意:
- 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
# 为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该实例化对象能添加的属性:
class Person(object):
__slots__ = ('name', 'age')
def __init__(self, name=None, age=None):
self.name = name
self.age = age
p = Person('llh', 23)
# 不能通过实例对象添加属性
# p.sex = 'boy' # 会报错 AttributeError: 'Person' object has no attribute 'sex'
# 可以添加类属性,不受限制
Person.sex = 'boy'
Person.like = 'shopping'
print(p.sex)
print(p.like)
# 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
class Child(Person):
pass
c = Child()
# 子类实例对象可以添加,不受限制
c.heiht = 60
print(c.heiht)
运行结果:
/home/longhui/Desktop/core_python_programming/venv/bin/python /home/longhui/Desktop/core_python_programming/venv/include/python_advanced_programming/part2/about__slots__.py
boy
shopping
60
Process finished with exit code 0