ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python面向对象之反射、元类

2022-03-31 12:00:31  阅读:192  来源: 互联网

标签:__ name Python self 元类 面向对象 init print


一、反射

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

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有