一、定义
类:具有相同属性和能力的一类事物
对象:类的具体表现
语法:
# 构建class LearnPython(object):\"\"\"类名必须首字母大写,驼峰体\"\"\"country = \"China\" # 静态变量def __init__(self, name, location): # 动态方法self.name = nameself.location = locationdef read(self):pass# 类# 查看类拥有的所有属性与方法print(LearnPython.__dict__)# {\'__module__\': \'__main__\',\'__doc__\': \'\\n 类名必须首字母大写,驼峰体\\n \',\'country\': \'China\',\'__init__\': <function LearnPython.__init__ at 0x000001E81E75E8C8>,\'read\': <function LearnPython.read at 0x000001E81E75E510>,\'__dict__\': <attribute \'__dict__\' of \'LearnPython\' objects>,\'__weakref__\': <attribute \'__weakref__\' of \'LearnPython\' objects>}# 实例化obj = LearnPython(\"Elvin\", \"北京\")# 查看实例所有的属性print(obj.__dict__) # {\'name\': \'Elvin\', \'location\': \'北京\'}# 查看实例拥有的方法【能力】print(obj.read()) # Elvin在北京看故宫# 对属性值的更改obj.name = \"LiLei\"del obj.nameprint(obj.__dict__)
二、实例化及创建对象的过程
一旦执行ClassName()类实例化动作,自动执行类中的new()方法,当前类中没有的则去基类object中执行new(cls,*args,**kwargs),创建一个对象空间,返回给ClassName(),
然后执行init方法,将对象空间传给self,init方法为这个对象空间初始化封装属性,
最后将封装好的属性返回给ClassName()
三、类与对象的小结
类名:1、类名查看类中所有的变量(字段),方法(函数):类名.__dict__2、类名对静态变量进行操作方法一、类名.__dict__[\"变量名\"] 只能查,报错不能增删改 **不用**方法二、类名.变量名 可增删改查 *****常用******3、类名对动态方法(函数)进行操作类名.__dict__[\"方法名\"] 或 类名.方法名 都只能查,不能增删改类调用函数必须给self赋值,哪怕赋的值是无用的,不然根据函数位置参数定义,就会因缺少参数报错对象:1、对象查看对象中所有的属性:对象名.__dict__ (因为对象没有建立自己的方法,故此时只能返回属性的字典)2、对象对对象本身的属性的操作方法1、对象名.属性 可以增删改查方法2、对象名.__dict__[属性名] 可以增删改查 ******不用*****3、对象对类中静态字段的操作3.1、对类静态变量(字段)的操作:只能查,不能增删改3.2、对类方法的操作:只能引用,不能增删改self 是位置参数,默认接收的是对象的对象空间,约定俗成叫self在类的非__init__方法中,也可以给对象添加一些属性,但如要使用这些属性,前提必须先执行这个方法类一旦创建了,就会执行里面的代码块,如果里面有print语句,就会执行,不像函数要调用才执行类 只能操作自己的属性及方法,无法操作对象的属性和方法,因为每个对象的属性都是自己独有的类属性的补充1、查看类的属性和方法dir(类名) ----->返回名字列表类名.__dict__ ----->返回一个字典2、特殊的类属性类名.__name__ # 类的名字类名.__doc__ # 类的文档字符串类名.__base__ # 类的第一个父类名(继承中从左到右)类名.__bases__ # 类的所有父类 -----> 返回一个元组类名.__dict__ # 类的所有属性与方法类名.__module__ # 类定义所在的模块 【在类所在的脚本中执行和 print(__name__) 一样都是固定的名字:__main__】类名.__class__ # 实例对应的类(仅新式类中)
四、类与对象的命令空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性静态属性就是直接在类中定义的变量(静态变量或者叫静态字段)动态属性就是定义在类中的方法类的静态属性是共享给所有对象的类的动态属性是绑定到所有对象的创建一个对象/实例就会创建一个对象/实例的名称空间(开始里面只有对应类对象的指针,以便找到类的__init__()方法来传空间地址及封装对象属性),存放对象/实例的名字,称为对象/实例的属性对象的查询顺序:先从对象空间去找,对象的空间没有此变量或者方法,通过对象中的类对象指针去类中寻找.类的查询顺序: 直接从类本身找.它无法查找对象的属性,因为是不同的命名空间无论创建多少个对象,都是独立开辟的命名空间,各个空间互相不能查找,干扰
- 计算一个类实例化了多少个对象?
class Test:count = 0def __new__(cls, *args, **kwargs):cls.count += 1return object.__new__(cls)def __init__(self):passprint(Test.count)
五、类的三大特性
继承
Python中一个类可以继承一个或多个父类,父类称为基类,子类称为派生类
作用:代码重用,规范接口,统一调用【规范调用方式,调用者不用关心实现】
class A:passclass B:passclass C(A,B):pass# 上面就是基本的一个继承关系,C类分别继承了A,B类的所有属性和方法,C类实现的实例都可以访问# 但有一点,如果子类和父类都有相同的方法,优先执行子类自己的方法# 所有的类,都继承基类Object类# 查看继承关系C.__bases__# 查看是否为某个类的对象【开发中经常使用】instance(obj,cls)如:instance(\"china\",str)# 查看是否为某个类的子类issubclass(cls,fater_cls)# 接口类定义一个抽象类,为一组子类定义一个通用的api,使调用方式统一,且接口类是不可以实例化的from abc import ABCMeta, abstractmethodclass Payment(metaclass=ABCMeta):@abstractmethoddef pay(self, money):\"\"\"通过装饰器,标识为抽象方法,所有子类都需实现本方法\"\"\"return# a = Payment() # Can\'t instantiate abstract class Payment with abstract methods payclass UnionPay(Payment):def __init__(self, year):self.year = yeardef pay(self, money):\"\"\"如果这里不实现此方法,就无法实例化\"\"\"print(\"222\")u = UnionPay(\"2021\") # Can\'t instantiate abstract class UnionPay with abstract methods pay
封装
隐藏对象的属性和实现细节,仅提供公共访问方式,我们实例化调用init就是一种封装
私有属性
Python中将在类中以双划线开头定义的变量或方法,称为私有属性或方法,仅提供给类内部调用
class Test(object):def __init__(self, action):self.action = actiondef __smoke(self):\"\"\"此方法仅仅用于类内部调用\"\"\"print(f\"class want ro {self.action}\")def wash(self):print(self.__smoke())print(f\"wash your {self.action}\")t = Test(\"face\")t.wash()t.somke() # AttributeError: \'Test\' object has no attribute \'somke\'
静态属性、静态方法、类方法
class Test(object):__TYPE = \"python小白养成记\"def __init__(self, action):self.__action = action@propertydef do(self):return f\"I can do:{self.__action}\"@do.setterdef do(self, v):\"\"\"改变do返回的值\"\"\"self.__action = v@do.deleterdef do(self):print(\"delete instance property is ok\")@staticmethoddef show_action():\"\"\"静态方法:实现普通方法,不需调用实例属性和方法\"\"\"print(\"just a ordinary function\")@classmethoddef action(cls):\"\"\"类方法\"\"\"return cls.__TYPEdef __repr__(self):return f\"just print the object instance:{self.__action}\"t = Test(\"eat\")# 静态属性property将类中方法实现的能力,调用时以属性的方式调用print(t.do) # I can do:eatt.do = \"kiss\"print(t.do) # I can do:kissdel t.do # Exception: can\'t delete instance property# 静态方法 staticmethod类中实现的方法,非实例方法,第一个参数不是self,就相当于普通方法t.show_action()# 类方法,调用方为类,虽然对象也可以调用,但不建议t.action()
多态
python天生多态,一类事物有多种状态,相同的需求不同的对象接收时执行不同的行为,但响应的接口是一致的
如:list、dict、set三种不同的对象,要删除元素,都实现了pop方法,虽然他们内部执行的逻辑不同,这就是pop的多种状态
反射【非常重要】
官方定义:程序可以访问、检测和修改它本身状态或行为的一种能力
小白解析:通过字符串的形式操作对象的属性【Python中的哲学:一切皆对象】
hasattr(obj,name) 对象是否有某个属性
getattr(obj,name,default=None) 获取对象的某个属性,如果没有则返回默认值
setattr(obj,name,value) 为对象设置一个属性name,其值为value
delattr(obj,name) 删除对象的某个属性,如果该属性不存在则抛出异常
# 示例:class Test(object):def __init__(self, code, desc):self.code = codeself.desc = descdef biz(self):return dict(code=self.code, desc=self.desc)obj = Test(0, \"success\")# 判断print(hasattr(obj, \"code\")) # True# 获取fun = getattr(obj, \"biz\", \"没有该属性时返回的值,不配置时为None\")print(fun()) # {\'code\': 0, \'desc\': \'success\'}# 设置新属性setattr(obj, \"data\", lambda self: dict(self.biz()))print(obj.data(obj)) # {\'code\': 0, \'desc\': \'success\'}# 删除属性delattr(obj, \"code\")# 查看对象的所有属性print(obj.__dict__) # {\'desc\': \'success\', \'data\': <function <lambda> at 0x000001E0835DE8C8>}# py文件也是对象,验证test.py文件中是否有某个方法import testif hasattr(test,\"func\"):ret = getattr(test,\"func\")(\"args\")print(ret)
常见的魔法方法
__new__(cls) 对象的构造方法__init__(self) 对象的初始化方法__call__(self,*args,**kwargs) 类的实例化对象如函数一般调用,obj=A(),obj(a,b)__del__(self) 析构方法,释放内存,动用del obj时使用,Python内部自动触发内存回收机制__repr__(self) 友好的以字符串显示对象,而不是一个内存地址空间,调用repr()方法__str__(self) 友好的以字符串显示对象,调用srt()方法__dir__(self) 显示对象的方法与属性,调用dir()__getattr__(self,name) 定义调用方试图获取一个不存在属性时的动作__setattr__(self,name,value) 定义当一个属性被设置时的行为__delattr__(self,name) 定义当一个属性被删除时的行为__getitem__(self,key) 定义获取容器指定元素的行为,相当于self[key]__setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value__delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]__enter__(self)1. 定义当使用 with 语句时的初始化行为2. __enter__ 的返回值被 with 语句的目标或者 as 后的名字绑定__exit__(self, exc_type, exc_value, traceback)1. 定义当一个代码块被执行或者终止后上下文管理器应该做什么2. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作