Python 高级用法

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__() 方法,分别用于返回对象的字符串表示和比较两个对象是否相等。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值