一、定义
类:具有相同属性和能力的一类事物
对象:类的具体表现
语法:
# 构建
class LearnPython(object):
"""
类名必须首字母大写,驼峰体
"""
country = "China" # 静态变量
def __init__(self, name, location): # 动态方法
self.name = name
self.location = location
def 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.name
print(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 = 0
def __new__(cls, *args, **kwargs):
cls.count += 1
return object.__new__(cls)
def __init__(self):
pass
print(Test.count)
五、类的三大特性
继承
Python中一个类可以继承一个或多个父类,父类称为基类,子类称为派生类
作用:代码重用,规范接口,统一调用【规范调用方式,调用者不用关心实现】
class A:
pass
class B:
pass
class 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, abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
"""通过装饰器,标识为抽象方法,所有子类都需实现本方法"""
return
# a = Payment() # Can't instantiate abstract class Payment with abstract methods pay
class UnionPay(Payment):
def __init__(self, year):
self.year = year
def 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 = action
def __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
@property
def do(self):
return f"I can do:{self.__action}"
@do.setter
def do(self, v):
"""改变do返回的值"""
self.__action = v
@do.deleter
def do(self):
print("delete instance property is ok")
@staticmethod
def show_action():
"""静态方法:实现普通方法,不需调用实例属性和方法"""
print("just a ordinary function")
@classmethod
def action(cls):
"""类方法"""
return cls.__TYPE
def __repr__(self):
return f"just print the object instance:{self.__action}"
t = Test("eat")
# 静态属性property
将类中方法实现的能力,调用时以属性的方式调用
print(t.do) # I can do:eat
t.do = "kiss"
print(t.do) # I can do:kiss
del 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 = code
self.desc = desc
def 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 test
if 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. 一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作