面向对象之反射

反射:

反射就是反省自省的意思。

反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

反射就是通过字符串操作属性

四个可以实现自省的函数: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)

""" 从大到小排 """
原文地址:https://www.cnblogs.com/sweet-i/p/11272580.html