标签:绑定 class关键字 区别 交互式 setting let 指定 属性 构造
判断第一个类是不是第二个类的子类, 返回True或者是false
class Foo:
pass
class Bar(Foo):
pass
print(issubclass(Bar, Foo)) # True
判断第一个参数是不是第二个参数的对象,返回True或者false
class Foo:
pass
class Bar:
pass
f = Foo()
print(isinstance(f, Foo)) # True
主要是指程序可以访问, 检测和修改它本身的状态或者行为的一种能力,也就是自省的意思,程序在运行的过程中,他是可以修改,检测,访问的自己的属性,修改对象的方式可以用点来修改, 函数跟模块就不能用哪个点来进行修改,在Python设计之初,就是把一切看做对象,这里就用到反射.
用户输入一段字符串,执行该字符串对应的方法
class Foo:
def run(self):
print(run)
def speak(self):
print(‘speak‘)
p = Foo()
cmd = input(‘请输入命令:‘)
if hasattr(p, cmd): # 判断某个属性是不是在这个对象中
run = getattr(p, cmd)
run()
else:
print(‘该命令不存在‘)
key = input("请输入key:")
value = input("请输入value:")
setattr(p, key, value) # 将key和value全都放置在p中
print(p.age) # 假如我们key设置为age,那么可以通过key就可以取出value值
# 动态的往对象中放方法
def test(a)
print(a)
print(p.__dict__) # {}
setattr(p, ‘test‘, test)
print(p.__dict__) # {‘test‘:<function test at 0x0000022B6ADFEA0>}
p.test(0)
# hasattr() 判断一个属性是不是在对象中
# getattr() 通过字符串获取属性和方法
# setattr() 通过字符串来设置属性和方法
# delattr() 通过字符串来删除属性和方法
有了反射的setattr方法,以后相加某个方法就可以随便的加了
# 动态的删除属性
# 原始的删除方法
p.name = ‘lqz
print(p.__dict__) # {‘name‘: ‘panshao‘}
del p.name # 直接拿属性
print(p.__dict__) # {}
# 动态删除p中属性为变量a的属性
a = input(‘请输入要删除的属性:‘)
delattr(p, a)
__str__
class Foo:
pass
f = Foo()
print(f)

如果不重写__str__,print打印会打印出内存地址,如果重写了会打印出你想要的
class Foo:
def __str__(self):
return ‘xxx‘
f = Foo()
print(f) # 当print对象的时候就去调用里面的函数,相当于print(f.__str__())
__repr__跟__str__相似, 在交互式的命令下直接写变量名,会执行__repr__,不用写print
__setattr__, __delattr__, __getattr__(重要)
class Foo:
def __init__(self, name)
self.name = name
f = Foo(‘panshao‘)
f.age # 没有age 这个属性,就会出现报错 这时候就可以用__getattr__
# __getattr__: 点拦截方法, 如果去对象中取属性, 取不到,会进入__getattr__
class Foo:
def __init__(self, name)
self.name = name
def __getattr__(self):
print(‘的点点滴滴‘)
f = Foo()
f.age # 打印出的点点滴滴
class Foo:
def __init__(self, name)
self.name = name
f = Foo(‘panshao‘) # 赋值时已经触发了__setattr__运行
print(f.name)
def __delattr__(self, item): #self传的是调用者自己 itme传的是调用错误的函数信息
print(‘----> from delattr‘)
# del self.item #无限递归了
#self.__dict__.pop(item) #同理直接操作字典
#__delattr__删除属性的时候会触发 #del f1.x #只要是删除操作就会调用__delattr__函数执行,值不存在也不会报错 # f1.__dict__[‘a‘]=3#我们可以直接修改属性字典,来完成添加/修改属性的操作 # del f1.a # print(f1.__dict__)
看一个例子:
#写一个类继承字典,让它可以 . 取值,可以中括号取值
class Mydict(dict):
def __init__(self,**kwargs):
super().__init__(**kwargs)
def __getattr__(self, item):
return self[item]
def __setattr__(self, key, value):
self[key]=value
di=Mydict(name=‘lqz‘,age=18)
print(di[‘name‘])
print(di.name)
di.sex=‘male‘
di[‘sex‘]=‘male‘
print(di[‘name‘])
print(di.name)
di.sex=19
print(di.sex)
di[‘sex‘]=‘male‘
print(di.sex)
__call__ 对象加括号会调用他
class Foo:
pass
f = Foo()
f() # 报错
class Foo:
def __call__(self)
print(‘xxx‘)
f = Foo()
f() # xxxx
产生类的类就叫元类, type类是产生所有类的元类,type能够实例化产生object, type也能继承object,type是内置的一个元类,所有的类都是由type实例化得到
class关键字底层实现原理:
# class 类名 : 就会把类构造出来
# 实际上是: 元类实例化产生类这个对象
# 类实例化产生对象,一定是: 类名()
# Person类是由type实例化产生,传一堆参数
# type(object_or_name, base, dict)
object_or_name: 类的名字, 是个字符串
# base: 是他的所有父类,基类
# dict: 名称空间, 是个字典,有方法,有属性
class Person: # Person 是类也是对象
def __init__(self, name):
self.name = name
def score(self):
print(‘分数是100分‘)
p = Person(‘panshao‘)
class的底层就是调用type来实例化产生类(对象), 自定义元类必须继承type, 写一个类继承type, 这种类就叫做元类
通过元类控制类的产生:
class Mymeta(type):
pass
# metaclass = Mymeta 指定这个类生成的时候,用自己写的Mymeta这个元类
class Person(metaclass=Mymeta): # Person 是类也是对象
def __init__(self, name):
self.name = name
def score(self):
print(‘分数是100分‘)
p = Person(‘panshao‘)
# 自定义元类:来控制类的产生,可以控制类名,可以控制类的关系(继承父类,控制类的名称空间)
通过元类来控制类的产生过程:
class Mymeta(type):
def __call__(self, *args, **kwargs):
# self是Person这个类
# 实例化产生一个Person类的对象,借助__new__来产生,需要把类传过去,才能产生对象
# obj 是Person类的对象,只不过是空的
obj = object.__new__(self) # obj是空的
# 调用__init__方法实现初始化
self.__new__(obj, *args, **kwargs) # 类来调用__init__方法,就是个普通函数,有几个参数就传几个参数
# obj.__new__(*args, **kwargs) # 对象来调用__init__方法,对象的绑定方法,会把自身传过来
class Person(metaclass=Mymeta):
def __init__(self, name):
self.name = name
def score(self):
print(‘分数是100分‘)
def __call__(self):
print("11111")
p = Person(‘panshao‘) # 自动触发init的执行 Person加括号就是调用元类的call方法
# 先触发元类的__call__
p() # p()是调用person的call
__new__:
class Person:
def __init__(self, name, age)
print("__init__")
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
# print("__new__")
# 生成一个空对象, return出去,在元类的__call__里调用了__init__来完成初始化
return object.__new__(cls)
p = Person(‘panshao‘, 18) # 打印出__new__ 奇怪为什么没有触发__init__,
print(p) # none
p = Person(‘panshao‘, 18) # 打印出__new__ 奇怪为什么没有触发__init__, p = Person(‘panshao‘, 18)先调用__call__方法,__call__再调用自己的self的__new__,就会得到一个空对象,假如我在__new__的方法中return一个1,那么这个空对象就是1,return后面的空对象一旦有值才会调用__init__
__new__和__init__的区别: __new__创建对象,必须有返回值, __init__初始化对象,就是给对象穿衣服
object.__new__(Person): 生成person类的对象, 空的
type.__new__(cls, name, bases, dic): 生成class这个类对象, 里面有东西
type类: __call__: 1. 调用Mymeta的__new__,得到类对象, 2. 调用Mymeta的__init__,完成对类对象的初始化
自定义的Mymeta元类: __call__ 1.调用了Person类的__new__,得到对象, 2. 调用Person类的__init__, 完成对象的初始化
整个过程中只有一个实例, 所有生成的实例都指向同一块内存空间
class Person:
def __init__(self, name , age)
self.name = name
self.age = age
p1 = Person(‘panshao‘, 18)
p2 = Person(‘bgon‘,19)
print(p1)
print(p2)

像上面这种情况就不是单例模式,他实例化出两个对象,单例模式是每次实例化出现的是同一个对象
实现单例的第一种方式:通过类的绑定方法
port = 3306
host = ‘127.0.0.1‘
class Sql:
_instance = None
def __init__(self, port, host):
self.port = port
self.host = host
@classmethod
def get_sigleton(cls):
if not cls._instance:
cls._instance = cls(‘port‘, ‘host‘)
return cls._instance
s1 = Sql.get_sigleton()
s2 = Sql.get_sigleton()
# 这样调用的话会实例化出不同的结果,我们现在做的就是要求每次拿到的实例化的结果都是一样的,我们可以在类的名称空间中加一个属性_instance
拿到的结果都是一样的,其实就是我每次要值得话,就去名称空间里面去取值就行
第二种方法: 通过装饰器
第二种方法:通过装饰器
当用户输入端口和地址,实例化产生新对象
当用户不输入端口和地址,每次拿到的对象,都是同一个
def get_sigoleton(cls):
#cls就是Sql这个类
import settings
_instance=cls(settings.PORT, settings.HOST)
_instance=Sql(settings.PORT, settings.HOST)
def wrapper(*args,**kwargs):
if len(args)!=0 or len(kwargs)!=0:
#表示传了参数,生成新对象
res=cls(*args,**kwargs)
return res
else:
return _instance
return wrapper
def get_sigoleton(cls):
_instance=None
def wrapper(*args,**kwargs):
if len(args)!=0 or len(kwargs)!=0:
#表示传了参数,生成新对象
res=cls(*args,**kwargs)
return res
else:
import settings
nonlocal _instance
if not _instance:
_instance=cls(settings.PORT, settings.HOST)
return _instance
return wrapper
@get_sigoleton #会把下面的Sql当中参数传入,相当于:Sql=get_sigoleton(Sql)
class Sql():
def __init__(self,port,host):
self.port=port
self.host=host
Sql=get_sigoleton(Sql)
s1=Sql()
s2=Sql()
s3=Sql(‘33306‘,‘192.168.1.1‘)
s4=Sql(‘33306‘,‘192.168.1.1‘)
print(s1)
print(s2)
print(s3)
第三种: 通过元类
#第三种,通过元类 #当用户输入端口和地址,实例化产生新对象 #当用户不输入端口和地址,每次拿到的对象,都是同一个 # class Mymeta(type): # def __init__(self,name,bases,dic): # #self 是Sql类 # import settings # #把实例化好的对象,放到了类的名称空间 # self._instance=self(settings.PORT, settings.HOST) # def __call__(self, *args, **kwargs): # #self是谁?是Sql类 # if len(args)!=0 or len(kwargs)!=0: # obj=object.__new__(self) # obj.__init__(*args, **kwargs) # return obj # else: # return self._instance # # class Sql(metaclass=Mymeta): #相当于 Sql=Mymeta(name,bases,dic) 这个会调用 Mymeta的__init__ 在里面已经向类的名称空间放了一个对象 # def __init__(self,port,host): # self.port=port # self.host=host # # print(Sql.__dict__) # s1=Sql() # #调用元类的__call__ # s2=Sql() # s3=Sql(‘33306‘,‘192.168.1.1‘) # print(s1) # print(s2) # print(s3)
标签:绑定 class关键字 区别 交互式 setting let 指定 属性 构造
原文地址:https://www.cnblogs.com/panshao51km-cn/p/11618911.html