Python元类
元类是用来创建类的类,可以在类被创建的时候定义类的结构和行为,可以看作是类的进一步抽象
类有多种创建方式
包括:
1.class关键字
2.type函数动态创建(第二个参数是父类元组bases)
MyDynamicClass = type('MyDynamicClass', (), {'k':'v', 'function': lambda self: print("Hello")})
3.元类和class关键字
在元类中,__new__
方法被用来控制创建类对象的过程。元类中,你可以通过重写__new__
方法来定制类的创建过程
cls
: 当前类的类对象,即元类自身。name
: 类的名称。bases
: 类的基类(父类)元组。dct
: 类的属性和方法的字典。
__metaclass__
是一个特殊的类属性,用于指定在创建类时要使用的元类。当你定义一个类时,Python 解释器会检查该类体中是否包含 __metaclass__
属性。如果存在 __metaclass__
,Python 将使用它指定的元类来创建类对象。如果没有指定 __metaclass__
,Python 将使用默认的元类,通常是 type
。大多数情况下,直接使用 metaclass
参数来指定元类更为常见。
class MyMetaClass(type):
def __new__(cls, name, bases, dct):
dct['x'] = 42
return super().__new__(cls, name, bases, dct)
class MyDynamicClass(metaclass=MyMetaClass):
y = 43
4.使用collections.namedtuple模块创建具有命名字段的简单类
from collections import namedtumple
Point = namedtuple('Point', ['x', 'y'])
p = Point(x=1, y=2)
5.使用类装饰器来使用元类
class MyMetaClass(type):
def __new__(cls, name, bases, dct):
dct['new_attribute'] = 'this is a new attribute'
return super.__new__(cls, name, bases, dct)
def my_decorator(cls):
return MyMetaClass(cls.__name__, cls.__bases__.dict(cls.__dict__))
@my_decorator
class MyClass():
existing_attribute = 'this is a existing attribute'
Python类方法@classmethod和静态方法@staticmethod
二者都是定义类级别方法的装饰器,但存在一些区别:
-
参数传递:
- 类方法 (
@classmethod
) 需要一个额外的参数,通常被命名为cls
,用于表示类本身。这个参数会自动传递类的引用。 - 静态方法 (
@staticmethod
) 不需要额外的参数,它不会隐式传递类的引用,也不会传递实例引用。
- 类方法 (
-
访问权限:
- 类方法 (
@classmethod
) 可以访问和修改类的状态,包括类变量。因为它有一个类的引用作为参数。 - 静态方法 (
@staticmethod
) 不能访问或修改类的状态,因为它没有类或实例的引用。它更像是一个独立的函数,只与类的命名空间有关。
- 类方法 (
-
调用方式:
- 类方法通过类名调用,但也可以通过实例调用。当通过实例调用时,实例会自动传递给
cls
参数。 - 静态方法通过类名调用,与实例无关,也可以通过实例调用。但不会自动传递类或实例引用。
- 类方法通过类名调用,但也可以通过实例调用。当通过实例调用时,实例会自动传递给
Python 内存管理和垃圾回收
python垃圾回收算法与所使用的解释器有关,python常用解释器:CPython、Jython、IronPython、PyPy、MicroPython、StacklessPython等。CPython使用引用计数+标记清除+分代回收,Jython和Ironthon依赖于相应的平台,PyPy使用追踪垃圾回收算法
引用计数是一种常见的方式,但不能解决循环依赖,这时需要标记清除算法辅助,一般而言标记算法是针对会包含其他对象引用的容器对象的,标记算法从根对象出发进行标记,第二轮将没有标记的对象添加进垃圾集合,这个过程会暂停程序的执行。根对象通常包括:全局变量、活动栈、静态对象
循环引用,指多个对象相互引用但是引用次数无法降为零,从而导致内存泄漏,内存泄漏是指由于错误的设计导致未能正确释放不再使用的内存,进而导致系统可用内存越来越少。
在python中我们可以通过手动启动垃圾回收并获取垃圾回收器的统计信息:
import gc
gc.collect()
stats = gc.get_stats()
print(stats)