编程语言
首页 > 编程语言> > Python面向对象之反射、元类

Python面向对象之反射、元类

作者:互联网

一、反射

  反射指的是一个对象应该具备,可以增、删、改、查属性的能力,通过字符串来操作属性。涉及四个函数,这四个函数就是普通的内置函数,没有下划线,但实现的功能和原理基本一致

hasattr(object,name)         # 判断对象是否实现某个属性,返回值是bool类型
setattr(object,name,value)   # 为对象增加新的属性
getattr(object,name,default) # 从对象中获取某个属性,返回值是str类型
delattr(object,)             # 从对象中删除某个属性,无返回值
class Person:
    def __init__(self,name,age,gender):
        self.name=name
        self.age=age
        self.gender=gender

p=Person("aaa",20,"woman")
# print(p.name)
print(hasattr(p,"name"))  # 判断是否是类的属性  True
if hasattr(p,"name"):
    print("我有name") 
    print(getattr(p,"name",None))  #从对象中取出属性,第三个值位默认值   aaa
    # 当属性不存在是返回默认值

# 为对象添加新的属性
a = setattr(p,"id","1234")
print(a)

# 从对象中删除对象
c = delattr(p,"id")
print(c)

  反射使用:

         1、一个类在定义的时候,可能一些属性的设计并不是很完美,而后期需要作出修改过或删除操作属性时,使用反射可以不需要修改源代码。反射其实就是对属性的增删改查,但如果直接使用内置的__dict__来操作,语法繁琐不便操作。

    2、另一个就是调用另一方提供的对象时,必须先判断这个对象是否满足需求,也就是判断是否是我们需要的属性和方法。动态添加模块功能。框架就与代码实现了彻底的耦合

 

二、元类 metaclass

  元类是创建类的类  所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化)。元类即 用于产生类的类。默认情况下所有类的元类都是type

  1、编写元类:

    只需要声明一个继承自type的类(使用class关键字)

    类只是对象,元类也只是类。元类的行为继承自type;因此任何type的子类都可以作为元类

    实例:例如控制类的名字必须以大驼峰体的方式来书写。用初始化的方法  我们只要找到类对象的类(元类),覆盖其中__ init__方法就能实现需求。不能修改源代码,所以应该继承type来编写自己的元类,同时覆盖__init__来完成需求。

# 定义一个元类
class MyType(type):
    def __init__(self,clss_name,bases,dict): #继承后用super调用
        super().__init__(clss_name,bases,dict)
        print(clss_name,bases,dict)
        if not clss_name.istitle():
          raise Exception("类名写错了~")
class pig (metaclass=MyType):
    print("绑定了元类~")
class Duck(metaclass=MyType):
    print("规定的协议要遵守~")

MyType("pig",(),{})

 

  2、元类中的__call__方法

    当调用类对象时会自动执行元类中的__call__方法,并将这个类本身作为第一个参数传入,以及后面的数,覆盖元类中的__call__之后,这个类无法产生对象,必须调用super().__call__来完成对象的创建,并返回其返回值。

#实现将对象的所有属性名称转化为大写
class MyType(type):
    def __call__(self, *args, **kwargs):
        new_arg = []   # 要求的书写规范
        for a in kwargs:
            new_arg.append(a.upper()) # 转换为大写
        print(new_arg)
        #print(kwargs)
        return super().__call__(*new_arg)

class Person(metaclass=MyType):
    def __init__(self,name,gender):
        self.name=name
        self.gender=gender

p=Person(name="aaa",gender="man")
print(p.gender)
print(p.name)
'''
['NAME', 'GENDER']
GENDER
NAME
'''

 

  3、__new__方法

    创建类的对象时,会先执行元类中的__new__ 方法。执行了__new__函数,就不会再执行__init__,因为__new__函数是真正用于创建类的方法,只有创建类成功了才会执行__init__函数,__new__必须要有返回值且返回值类型为__type__时才会执行__init__函数,

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)
        print(obj)           #<class '__main__.A'>
        return obj          #无返回值,不执行init方法

    def __init__(self,a,b,c):
        super().__init__(a,b,c)
        print("init run")            #有返回值就执行init run

class A(metaclass=Meta):
    pass
print(A)             #此时有返回值执行init方法,就执行这个
'''
<class '__main__.Meta'>
('A', (), {'__module__': '__main__', '__qualname__': 'A'})
{}
new run
init run
<class '__main__.A'>
'''

 

  4、单例

    单例是指的是单个实例,指一个类只能有一个实例对象。为了节省资源,当两个对象的数据完全相同时 则没有必要占用两份资源。

# 单例n元类
class Single(type):
    def __call__(self, *args, **kwargs):
        if hasattr(self,"obj"): #判断是否存在已经有的对象
            return getattr(self,"obj") # 有就返回

        obj = super().__call__(*args,**kwargs) # 没有则创建
        print("这下有了")
        self.obj = obj # 并存入类中
        return obj

class Student(metaclass=Single):
    def __init__(self,name):
        self.name = name

class Person(metaclass=Single):
    pass

# 只会创建一个对象
Person()
Person()

 

四、冒泡算法:冒泡排序

  冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

def bubbleSort(arr):
    n = len(arr)
    # 遍历所有数组元素
    for i in range(n):
        print(i)
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]

arr = [64, 34, 25, 12, 22, 11, 90]
#即用64与34比较,交换二者位置,再与25比较又交换位置,以此类推
bubbleSort(arr)
print("排序后的数组:")
for i in range(len(arr)):
    print("%d" % arr[i])

 

标签:__,name,Python,self,元类,面向对象,init,print
来源: https://www.cnblogs.com/wmtly/p/16081110.html