反射:
反射就是反省自省的意思。
反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。
反射就是通过字符串操作属性
四个可以实现自省的函数:hasattr;getattr;setattr;delattr
hasattr:
判断某个对象是否存在某个属性。
# hasattr
class Person:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
p = Person("jack",18,"man")
print(p.name)
print(hasattr(p,"name")) # 判断某个对象是否存在某个属性
getattr:
从对象中取出属性,当对象中有默认值的时候,属性不存在的时候会返回默认值。
# getattr
class Person:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
p = Person("jack",18,"man")
print(p.name)
print(hasattr(p,"name"))
if hasattr(p,"name"): # 判断某个对象是否存在某个属性
print(getattr(p,"names",None)) # 从对象中取出属性,第三个值位默认值 当属性不存在是返回默认值
setattr:
为对象添加新属性
# setattr
class Person:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
p = Person("jack",18,"man")
print(p.name)
# 为对象添加新的属性
setattr(p,"id","123")
print(p.id)
delattr:
从对象中删除属性
# delattr
class Person:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
p = Person("jack",18,"man")
print(p.name)
delattr(p,"name")
print(p.name)
"""
反射其实就是对属性的增删改查,但是如果直接使用内置的__dict__来操作,语法繁琐,不好理解
另外一个最主要的问题是,如果对象不是我自己写的是另一方提供的,我就必须判断这个对象是否
满足的要求,也就是是否我需要的属性和方法
"""
框架:
反射被称为框架的基石,为什么
因为框架的设计者,不可能提前知道你的对象到底是怎么设计的
所以你提供给框架的对象 必须通过判断验证之后才能正常使用
判断验证就是反射要做的事情,当然通过__dict__也是可以实现的,
其实这些方法也就是对__dict__的操作进行了封装。
元类:
元类是什么?元类是用于创建类的类,
万物皆对象,类当然也是对象
对象是通过类实例化产生的,如果类也是对象的话,
必然类对象也是有另一个类实例化产生的
默认情况下所有类的元类都是type
验证:
class Person:
pass
p = Person()
print(type(p))
print(type(Person))
"""Person类是通过type类实例化产生的 """
我们学习元类的目的:
高度的自定义一个类,例如控制类的名字必须以大驼峰体的方式来书写。
类也是对象,也有自己的类:
"""
我们的需求是创建类对象做一些限制
想到了初始化方法 我们只要找到类对象的类(元类),覆盖其中 init方法就能实现需求
当然我们不能修改源代码,所以应该继承type来编写自己的元类,同时覆盖init来完成需求
"""
class MyType(type):
def __init__(self,clss_name,bases,dict):
super().__init__(clss_name,bases,dict)
print(clss_name,bases,dict)
if not clss_name.istitle():
raise Exception("好好写类名")
# 为pig类指定了元类为MyType
class Pig(metaclass=MyType):
pass
class Duck(metaclass=MyType):
pass
""" 只要继承了type 那么这个类就变成了一个元类 """
元类中call方法:
当你调用类对象时,会自动执行元类中__call__方法,并将这个类本身作为第一个参数传入
以及后面的一堆参数覆盖元类中的__call__之后,这个类就无法产生对象,必须调用super().__call__
来完成对象的创建并返回其的返回值。
使用场景:
当你想要控制对象的创建过程时,就覆盖__call__方法
当你想要控制对象的创建过程时,就覆盖__init__方法
class MyMeta(type):
def __init__(self,name,bases,dict):
super().__init__(name,bases,dict)
print("init run")
def __call__(self, *args, **kwargs):
print("元类 call run")
print(self)
print(args)
print(kwargs)
return super().__call__(*args,**kwargs)
class Dog(metaclass=MyMeta): # === Dog = MyMate("Dog",(),{})
def __init__(self,name):
self.name = name
def __call__(self, *args, **kwargs):
print("call run")
d = Dog("大黄")
d = Dog("旺财")
print(d.name)
"""一旦覆盖了call必须调用父类的call方法来产生对象并返回这个对象 """
new方法:
当你要创建类对象时,会首先执行元类中的__new__方法,拿到一个空对象,然后会自动调用__init__
来对这个类进行初始化操作 需要注意的是:如果你覆盖了该方法则必须保证,new方法必须有返回值且必须是,对应的类对象
class Meta(type):
def __new__(cls, *args, **kwargs):
print(cls) # 元类自己
print(args) # 创建类需要的几个参数 类名,基类,名称空间
print(kwargs) #空的
print("new run")
# return super().__new__(cls,*args,**kwargs)
obj = type.__new__(cls,*args,**kwargs)
return obj
def __init__(self,a,b,c):
super().__init__(a,b,c)
print("init run")
class A(metaclass=Meta):
pass
print(A)
""" new方法和init 都可以实现控制类的创建过程,init更简单 """
单例设计模式:
单例设计模式主要用于解决某种固定问题的套路
例如:MVCMTV等
单例:它指的是一个类产生一个对象
为什么要使用单例:单例是为了节省 资源,当一个类的所有对象属性全部相同时,则没有必要创建
多个对象
class Single(type):
def __call__(self, *args, **kwargs):
if hasattr(self,"obj"): #判断是否存在已经有的对象
return getattr(self,"obj") # 有就返回
obj = super().__call__(*args,**kwargs) # 没有则创建
print("new 了")
self.obj = obj # 并存入类中
return obj
class Student(metaclass=Single):
def __init__(self,name):
self.name = name
class Person(metaclass=Single):
pass
# 只会创建一个对象
Person()
Person()
冒泡排序:
依次从左往右的顺序循环对比
圈数是元素的个数减一
次数是元素个数 -1 - (圈数索引)
l = [9, 587, 2, 616, 5, 1, 3, 69, 4, 8, 8, 43, 9, 32, 56, 55, 35, 45, 25, 15,]
for i in range(len(l) - 1):
for j in range(len(l) - 1 - i):
if l[j] < l[j+1]:
l[j], l[j+1] = l[j+1], l[j]
print(l)
""" 从大到小排 """