1、getattr:反射
class Demo():
def start(self, *args, **kwargs):
print("start")
def shutdown(self, *args, **kwargs):
print("shutdown")
def update_status(self, **kwargs):
action = kwargs['action']
func = getattr(self, action, None)
if not func:
raise Exception
task_id = func(**kwargs)
demo = Demo()
filter = {'action': 'start'}
demo.update_status(**filter)
# echo start
通过入参来选择调用的函数。
2、__doc__: 是一个特殊的类属性,用于存储类的文档字符串(docstring)
class Debug:
"""
This is a class for debugging
"""
class NewDebug(Debug):
__doc__ = Debug.__doc__
# NewDebug
main = NewDebug()
print(main.__doc__) # This is a class for debugging
上面例子中,如果父类有了非常详细的描述并且子类描述也一致,可以使用继承的方式继承父类的描述;
class Debug:
"""
This is a class for debugging
"""
class NewDebug(Debug):
"""
new doc
"""
__doc__ = Debug.__doc__
# NewDebug
main = NewDebug()
print(main.__doc__) # This is a class for debugging
如果继承了父类的__doc__那么子类的相关描述将不展示。
3、__dict__: 是一个实例属性,不是类属性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class NewPerson(Person):
__dict__ = Person.__dict__
在Python中,尝试将__dict__属性直接赋值给子类(如NewPerson)是不正确的,因为__dict__是一个实例级别的属性,用于存储对象的属性。类级别的__dict__属性实际上并不存在,因此Person.__dict__会返回一个错误。
如果你想要子类(NewPerson)继承父类(Person)的属性和方法,并且想要在类级别上做一些额外的设置,你应该在子类的__init__方法中调用父类的__init__方法,而不是尝试操作__dict__属性。
正确的例子,展示了如何在子类中调用父类的__init__方法来继承属性:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class NewPerson(Person):
def __init__(self, name, age, additional_info):
# 调用父类的__init__方法来初始化从Person继承的属性
super().__init__(name, age)
# 添加子类特有的属性
self.additional_info = additional_info
总结:Python的类继承机制会自动处理属性和方法的继承,你通常不需要直接操作__dict__或其他底层机制来实现这一点。如果你需要添加或覆盖方法或属性,直接在子类中定义它们即可
4、__name__:是一个内置的特殊属性,它表示对象的类型名称,对于类来说,__name__通常就是类的名字(作为一个字符串)
class Person:
pass
class NewPerson(Person):
pass
print(Person.__name__) # 输出: 'Person'
print(NewPerson.__name__) # 输出: 'NewPerson'
5、__slots__ 是一个类变量,用于声明实例属性应该存储在一个固定大小的数组中,而不是使用通常的字典方式(即实例的 dict 属性)
优点:
1、内存效率:使用 __slots__ 可以减少内存使用,因为实例不再需要存储一个字典对象来管理其属性。
2、属性查找速度:由于属性是存储在固定大小的数组中的,所以属性查找速度会更快。
3、限制动态属性添加:使用 __slots__ 的类不允许你动态添加新的实例属性,除非你显式地修改了 __slots__ 定义或者重写了
__setattr__ 方法。
缺点:
尝试给 NewPerson 实例添加一个不在 __slots__ 列表中的属性(如 address)将会导致 AttributeError 异常。
class Person:
pass
class NewPerson(Person):
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age = age
# 创建一个 NewPerson 实例
np = NewPerson("Alice", 30)
# 访问属性
print(np.name) # 输出: Alice
print(np.age) # 输出: 30
# 尝试添加不在 __slots__ 中的属性将会引发 AttributeError
# np.address = "123 Main St" # 这会抛出 AttributeError
NewPerson 类使用了 __slots__ 来限制其实例只能有 name 和 age 这两个属性。尝试给 NewPerson 实例添加一个不在 __slots__ 列表中的属性(如 address)将会导致 AttributeError 异常。
需要注意的是,由于 NewPerson 继承自 Person,如果 Person 类使用了 __slots__,那么 NewPerson 的 __slots__ 应该包含 Person 的 __slots__ 中的所有属性,以避免覆盖它们。如果 Person 没有使用 __slots__,那么 NewPerson 的 __slots__ 将只包含它自己的属性。
另外,由于 __slots__ 限制了动态属性添加,因此在设计类时要谨慎使用它,确保你了解它的限制和潜在影响。
6、__file__:一个特殊的内置变量,它包含了当前执行的脚本或模块文件的路径
作用:
- 通常与 os.path 模块一起使用,以便进行路径操作,如获取文件的绝对路径或相对于脚本的目录路径。
7、__module__:一个内置属性,它表示对象(通常是函数、类或变量)所在的模块的名称。
当你查看一个Python对象时,这个属性可以告诉你该对象是从哪个模块中定义的。
例如,假设你有两个模块,module_a.py 和 module_b.py,每个模块中都定义了一个函数:
# module_a.py
def function_a():
pass
module_b.py:
def function_b():
pass
如果你从另一个脚本中导入这两个函数并打印它们的 module 属性,你会看到以下输出:
from module_a import function_a
from module_b import function_b
print(function_a.__module__) # 输出: module_a
print(function_b.__module__) # 输出: module_b
对于在交互式环境中定义的对象(例如直接在Python shell或Jupyter Notebook中),__module__ 属性通常会设置为 "__main__",表示这些对象是在主程序中定义的。
def main_function():
pass
print(main_function.__module__) # 输出: "__main__"
了解 __module__ 属性在调试、反射(reflection)或动态代码生成时特别有用,因为它允许你追踪对象的来源。
8、__annotations__:一个内置属性,它提供了对函数或变量注解的访问
def demo(name: str, age: int):
return {name, age}
print(demo.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>}
9、@dataclass 是 Python 的一个装饰器,它使得创建一个类,这个类拥有自动生成 init(), repr(), eq() 等特殊方法变得非常简单。
tips: python>=3.7
from dataclasses import dataclass
@dataclass
class Person:
name: str
age: int
city: str = "New York" # 默认值
# 创建一个 Person 实例
p = Person("Alice", 30)
# 访问属性
print(p.name) # 输出: Alice
print(p.age) # 输出: 30
print(p.city) # 输出: New York
# 自动生成的 __repr__ 方法
print(p) # 输出: Person(name='Alice', age=30, city='New York')
# 自动生成的 __eq__ 方法
p2 = Person("Alice", 30)
print(p == p2) # 输出: True
在这个例子中,@dataclass 装饰器为 Person 类自动生成了 __init__() 方法,用于初始化 name, age, 和 city 属性。同时,它还自动生成了 __repr__() 和 ___eq__() 方法,分别用于返回对象的字符串表示和比较两个对象是否相等。