1.元类 type
- type元类,又称为构建类,python中一切皆对象,类也可以理解为对象,python中自己定义的类,以及大部分内置类,都是由type元类实例化得来的
元类type
class A:
pass
obj = A()
print(type('abc')) #<class 'str'>
print(type([1,2,3])) #<class 'list'>
print(type((22,33))) #<class 'tuple'>
print(type(A)) #<class 'type'>
print(type(str)) #<class 'type'>
print(type(type)) #<class 'type'>
print(type(object)) #<class 'type'>
-
type 与 object 的关系 : object是type类的实例,而type类是object类的子类
-
print(type(object)) # <class 'type'> object类是type类的一个实例化对象
print(isinstance(type,object)) #True 结果为真,说明object是type类的实例化对象
print(issubclass(type,object)) #True 结果为真,说明type类是object类的子孙类
-
2.反射
- 定义:程序对自己内部代码的一种自省方式
- 官方:主要是指程序可以访问检测和修改它本身状态或行为的一种能力/自省
- python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
2.1 四种方法,四个方面分析 **一切基于万能的点能够做到的
hasattr 判断是否存在 True False(万能的点是否成立)
getattr 判断有就得到结果,没有就报错,可以设置返回值就不报错了
setattr 添加对象属性
delattr 删除对象属性
-
实例对象
class A: country = "中国" def __init__(self,name,age): self.name = name self.age = age def func(self): print("in A func") obj = A("alex",22) #hasattr 万能的点能调用的都可以用 print(hasattr(obj,"name")) #True print(hasattr(A,"func")) #True print(hasattr(A,"name")) #False print(getattr(obj,"country")) #中国 print(getattr(obj,"name")) #alex print(getattr(obj,"func")) #<bound method A.func of <__main__.A object at 0x000000D16FB1C710>> f = getattr(obj,"func") f() #调用func函数 print(getattr(A,"name")) #报错 print(getattr(obj,"sex")) #报错 print(getattr(A,"name","不存在")) #不存在 print(getattr(obj,"sex",None)) #None print(obj.__dict__) #{'name': 'alex', 'age': 22} setattr(obj,"sex","男") print(obj.__dict__) #{'name': 'alex', 'age': 22, 'sex': '男'} print(obj.__dict__) #{'name': 'alex', 'age': 22} delattr(obj,"name") print(obj.__dict__) #{'age': 22} delattr(obj,"country") #报错 无此属性
-
类 #上边,类名调用的是类的映射 对象调用的是对象的映射
-
其他模块
tbjx.py文件中的内容 name = '太白金星' def func(): print('in tbjx func') class C: area = '北京' def __init__(self,name): self.name = name def func(self): print('in B func')
1. 找到tbjx对象的C类,实例化一个对象. import tbjx obj = getattr(tbjx,"C")(tbjx.name)
2. 找到tbjx对象 的C类,通过对C类这个对象使用反射取到area. import tbjx obj = getattr(tbjx,"C")(tbjx.name) print(getattr(obj,"area")) #北京
3. 找到tbjx对象的C类,实例化一个对象,对对象进行反射取值. import tbjx obj = getattr(tbjx,"C")(tbjx.name) print(getattr(obj,'name')) #太白金星
-
本模块
a = 666 def func1(): print('in func1') def func2(): print('in func2') def func3(): print('in func3') def func4(): print('in func4') import sys print(sys.modules[__name__]) #当前文件模块实例化 print(getattr(sys.modules[__name__],"a")) #666 getattr(sys.modules[__name__],"func1")() #in func1 调用并执行函数
循环上述函数 lst = [func1,func2,func3,func4] for i in lst: i()
lst = [f"func{i}" for i in range(1,5)] # print(lst) for i in lst: getattr(sys.modules[__name__],i)()
3.函数与方法的区别 ***函数都是显性传参,方法都是隐性传参.
from types import FunctionType 函数
from types import MethodType 对象
python 中一切皆对象, 类在某种意义上也是一个对象,python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的.
python 中一切皆对象, 函数在某种意义上也是一个对象,函数这个对象是从FunctionType这个类实例化出来的.
python 中一切皆对象, 方法在某种意义上也是一个对象,方法这个对象是从MethodType这个类实例化出来的.
3.1 通过打印函数(方法)名确定
def func1():
pass
class A:
def func(self):
pass
print(func1) #<function func1 at 0x000000EB2BF7DA60> #函数
通过类名调用的类中的实例方法叫做函数
print(A.func) #<function A.func at 0x000000EB2BF7DAE8> #函数
通过对象调用的类中的实例方法叫方法
print(obj.func) #<bound method A.func of <__main__.A object at 0x000000EB2BF7C240>> #方法
3.2 通过借助模块判断是方法还是函数
from types import FunctionType
from types import MethodType
def func1():
pass
class A:
def func(self):
pass
obj = A()
print(isinstance(func1,FunctionType)) # True
print(isinstance(A.func,FunctionType)) # True
print(isinstance(obj.func,FunctionType)) # False
print(isinstance(obj.func,MethodType)) # True
3.3函数都是显性传参,方法都是隐性传参.
class A:
name = "我不是第一个"
@classmethod
def func(cls):
print(cls.name)
@staticmethod
def func1(argv):
print(f"{argv}")
obj = A()
A.func() #隐形传参,第一个参数默认把A传给了cls
A.func1("显性传参") #显性传参
obj.func() #隐形传参,第一个参数默认把A传给了cls
obj.func1("显性传参") #显性传参
4.双下方法
特殊的双下方法: 原本是开发python这个语言的程序员用的.源码中使用的.
4.1 __len__ 方法 自定义类中必须要有返回值,且返回值必须是数字(0-正无穷),其他都报错 len()就触发了方法
class A:
def __len__(self):
print(666)
return 222
a = A()
print(len(a)) # 666 222
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __len__(self):
print(self.__dict__) #{'name': '太白', 'age': 28}
return len(self.__dict__) #内置函数len方法
a = A("太白",28) #实例化对象
print(len(a)) # 2
4.2 __hash__ 方法 自定义类中必须要有返回值正负整数都可以,但是-1得到-2
class A:
pass
obj = A()
print(hash(obj)) #触发object类的__hash__方法
class A:
def __init__(self):
self.a = 1
self.b = 2
def __hash__(self):
return -1 #唯一不正常的返回结果-2
obj = A()
print(hash(obj))
4.3 __str__ 方法 自定义类中必须要有返回值且必须是字符串
class A:
def __init__(self,name,age):
self.name = name
self.age =age
def __str__(self):
return f'姓名: {self.name} 年龄: {self.age}'
a = A("太白",25)
b = A("宝元",26)
c = A("日天",27)
# 打印对象触发__str__方法
print(a)
print(b)
print(c)
# 直接str转化也可以触发.
print(str(a))
4.4 _str__ 方法 和_repr__ 方法共同存在时,只执行前者
class A:
def __init__(self,name,age):
self.name = name
self.age = age
def __repr__(self):
return "我执行不了了"
def __str__(self):
return "我优先"
a = A("太白",25)
b = A("宝元",26)
c = A("日天",27)
# 打印对象触发__str__方法
print(a)
print(b)
print(c)
# 直接repr转化也可以触发.
print(repr(a))
class A:
__instance = None
def __init__(self,name):
self.name = name
#不能设置返回值因为都是类名()调用的
#不能同时接收多个返回值
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = object.__new__(cls)
#类名.属性,改变属性
return cls.__instance
#返回后猜测还有一个回调机制去调用__init__方法
obj = A("alex")
print(obj)
obj1 = A("taibai")
print(obj1)
obj2 = A("baoyuan")
print(obj2)
print(obj.name) #baoyuan
print(obj1.name) #baoyuan
print(obj2.name) #baoyuan
#三个共用一个内存空间,变量一直在改