python动态添加属性和方法、__slots__的作用

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(arg): # 第一个参数接收Person object
    print(arg)    # <__main__.Person object at 0x7f33db18bc18>
    print('%s正在跑...' % arg.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. 运行的过程中删除属性、方法

删除的方法:

  1. del 对象.属性名
  2. delattr(对象, "属性名")
# 删除属性
print(p1.sex)

# del Person.sex
delattr(Person, 'sex')

# print(p1.sex) # AttributeError: 'Person' object has no attribute 'sex'

通过以上例子可以得出一个结论:相对于动态语言,静态语言具有严谨性!所以,玩动态语言的时候,小心动态的坑!

那么怎么避免这种情况呢? 请使用__slots__

__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

猜你喜欢

转载自blog.csdn.net/qq_41020281/article/details/80265917
今日推荐