侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

Python3类

2023-12-13 星期三 / 0 评论 / 0 点赞 / 92 阅读 / 11144 字

1.类的定义 class Heap:# def __new__(cls): # 创建实例,传入cls类本身# # 可以改变实例创建的行为,这就是元编程的体现# pa

1.类的定义

class Heap:#    def __new__(cls):  # 创建实例,传入cls类本身#        # 可以改变实例创建的行为,这就是元编程的体现#        pass # 通常不写,除非要改变默认的创建实例的行为# 所有类的__class__都是type或其子类的实例    class_var = 1 # 类变量,被实例共享引用,可被类.操作修改,赋值修改后产生个性化    class_list = [] # 类可变变量,赋值改变,修改不变    # 对象创建完成后,立刻执行,self代表实例本身    def __init__(self, *args, **kwargs): # 通常叫做构造函数,在python中更多的叫做初始化函数        self.kwargs = kwargs # 没有显示定义__init__时,会使用默认的__init_        self.x = x # 普通实例变量        self.__y = y # 仅双下划线开始的变量是私有实例变量,理论上,仅可被内部方法访问;实际上._类名__私有变量__        self._z = z # 单下划线开始的变量是共有的        self.__m__ = 1 # 双下划线开始结尾的变量是公有的(特殊)        def add(self, x): # 实例方法        pass # “第一个参数”必须是self        @classmethod #使用装饰器,定义类方法,用于让实例能调用    def method_of_class(cls): # “第一个参数”是cls,类本身        print('method of class')            @staticmethod # 用于让实例能调用    def static_method(): # 静态方法,默认不能被实例调用        print('static method') # 不传入“第一个参数”

2.类的封装

class G:    __private_var = 'private'    status1 = '...'    @property # 使用装饰器,把x方法装饰为属性,通过.操作直接访问    def status1(self):        return self.__private_var        @status1.setter # 被x.setter装饰的方法,使方法属性可被直接修改    def status11(self, value):        if value in ('closed', 'openning'):            self.__private_var = value        else:            raise ValueError(value)                @status1.deleter    def status1(self):        raise NotImplementedError('you can nott')

类变量、方法属性、实例变量,会根据代码的执行顺序进行覆盖:

    类变量、方法属性是定义类的时候定义的,所以会根据代码写的顺序进行覆盖

    实例变量在类定义后实例化的时候定义

3.类的继承

# 所有类都继承于object类class H(G): # H类继承G类,会创建H类MRO表    def print(self):        print('i am H')        super().print() # 调用H父类的方法        super(G, self).print() # 调用G父类的方法        #print(super().private) # 无法访问父类的实例变量        #print(super().pub) # 可访问类变量H.mro()[__main__.H, __main__.G, __main__.Base, object]可通过super(type, self),返回type的父类(准确来说是mro表的下一个类)的指代super对象,进行调用type类的方法

4.运算符重载

class Complex:    def __init__(self, real, imag=0): # 方法前后双下划线,称为专有方法或魔术方法        self.real = real        self.imag = imag    # 重载int类方法    def __add__(self, other): # 重载+法,只能__add__跟默认的+方法重载        return Complex(self.real + other.real, self.imag + other.imag)        def __sub__(self, other): # 重载-法,只能__sub__跟默认的-方法重载        return Complex(self.real - other.real, self.imag - other.imag)        def __mul__(self, other): # 重载*法,只能__mul__        return Complex(self.real * other.real - self.imag * other.imag,                      self.real * other.imag + self.imag * other.imag)

5.内建方法

class A:    def __init__(self):        self.length = 1        def __len__(self):        return self.length        def __bool__(self):        return Falsea = A()len(a)bool(a)

6.可调用对象

class Add:    def __call__(self, a, b):#有__call__方法的对象,是可调用对象,可以直接调用        return a + b # __init__ 有__call__方法a = Add() # 所有函数都是可调用对象a(1, 2) # 当调用一个可调用对象时,实际上调用的是__call__方法3callable(a) # 内置函数callable用于判断一个对象是否是可调用对象True

7.对象可视化

class Complex:    def __init__(self, real, imag=0):        self.real = real        self.imag = imag        def __str__(self):        if self.imag > 0:            return ' {} + {}i'.format(self.real, self.imag)        elif self.imag < 0:            return ' {} - {}i'.format(self.real, self.imag * -1)        return ' {}'.format(self.real)        def __repr__(self):        return '<{}.{}({}, {}) at {}>'.format(self.__module__, self.__class__.__name__, self.real, self.imag, hex(id(self)))c = Complex(1, 2)str(c)' 1 + 2i'c<__main__.Complex at 0x7f88f5eb7a58><__main__.Complex(2, 3) at 0x7f88f5ed25f8> # 修改了__repr__方法后

8.context

class Context:    def __init__(self):        print('init')    # 同时具有__enter__和__exit__方法的类    def __enter__(self):        print('enter')            def __exit__(self, *args, **kwargs):        print('exit')with Context()as a: # with后面跟一个实例,as把__enter__方法的返回值赋给a    print('block') # 按照__init__,__enter__,block,__exit__顺序执行成对出现操作,并且必须确保两个都执行    资源打开/关闭    枷锁/解锁进入代码块之前要执行一些操作(__enter__)    初始化    权限判断离开代码块时要执行一些操作(__exit__)
# 标准库里的context装饰器import [email protected] test():    print('enter') # __enter__    try:        yield 123 # block    finally:        print('exit') # __exit__

9.反射

#通俗:可以使用代码,获取对象本身的一些属性,例如对象的字段、方法等dir(a) # 获取实例的属性和方法a.__class__ # 获取当前模块类__main__.Aa.__class__.__name__ # 获取当前类名'A'a.__dict__ # 获取属性{'y': 1}a.__doc__ # 文档字符串'''doc'''a.__module__ # 当前所在模块'__main__'
class A:    x = 1        def __init__(self):        self.y = 1    # getattr 内建函数,调用 __getattribute__,通过字符串的方式访问类的属性    # 如果类定义了__getattr__ 方法,当输出不存在时,将会访问__getattr__方法    def __getattr__(self, name, default=None):        return 'missing proptery'    # 当定义__getattribute__方法的时候,访问实例的属性的时候,总是调用__getattrbute__    def __getattribute__(self, *args, **kwargs):        return '1111'    a = A()setattr(a, 'x', 3) # setattr设置object属性(实际调用__setattr__),存在即修改,不存在即创建delattr(a, 'num') # 删除属性

10.描述器

class Int:    def __init__(self, name):        print('init')        self.name = name    # __get__和__set__方法成对出现    def __get__(self, instance, cls): # 访问属性时        print('access')        if instance is None:            return self        return instance.__dict__[self.name]        def __set__(self, instance, value): # 修改属性时        print('set')        instance.__dict__[self.name] = value            def __delete__(self, instance): # 删除属性时        raise TypeError('not allowed')# 用于控制对属性的访问、赋值和删除class A:    x = Int('x') # 实例化描述器,传入任意值填补Int.__init__的参数        def __init__(self, x):        self.x = x

11.描述器的应用

# property装饰器,把类方法改为类属性class Property:    def __init__(self, fget=None, fset=None, fdel=None):        self.fget = fget        self.fset = fset        self.fdel = fdel        print('initP')            def __get__(self, instance, cls):        print('get')        if instance is None: # instance是调用Property实例方法的实例a            return self        if not callable(self.fget):            raise AttributeError()        return self.fget(instance) # self.fget即A.x        def __set__(self, instance, value):        print('set')        if not callable(self.fset):            raise AttributeError()        self.fset(instance, value)            def __delete__(self, instance):        print('delete')        if not callable(self.fdel):            raise AttributeError()        self.fdel(instance)            def setter(self, fset):        print('setter')        #self.fset = fset        return Property(self.fget, fset, self.fdel)            def delete(self, fdel):        print('delete')        #self.fdel = fdel        return Property(self.fget, self.fset, fdel)            def print(self):        print(self.fget)class A:    def __init__(self, x):        print('init2')        self.__x = x            @Property # 传入x方法作为fget,实例化了类装饰器    def x(self):        print('x')        return self.__x        # x = Property(A.x)        @x.setter    def x(self, value):        print('set_x')        self.__x = value    # x = x.setter(A.x) = Property(x.fget, A.x, x.del)
# classmethod装饰器from functools import wraps, partialclass Classmethod:    def __init__(self, method):        wraps(method)(self)            def __get__(self, instance, cls):        return partial(self.__wrapped__, cls)class C:    @Classmethod    def method(cls):        print(cls)            @Classmethod    def method2(cls, x):        print(cls)        print(x)
# 对类变量做类型检查class Typed:    def __init__(self, name, required_type):        self.name = name        self.required_type = required_type            def __get__(self, instance, cls):        if instance is None:            return self        return instance.__dict__[self.name]        def __set__(self, instance, value):        if not isinstance(value, self.required_type):            raise TypeError(' {} required type {}'.format(self.name, self.required_type))        instance.__dict__[self.name] = value        class A:    x = Typed('x', int)    y = Typed('y', str)        def __init__(self, x, y):        self.x = x        self.y = y

 

广告 广告

评论区