首页 > 编程语言 >python(面向对象之元类,魔法方法)

python(面向对象之元类,魔法方法)

时间:2022-11-08 18:02:52浏览次数:38  
标签:__ python 元类 面向对象 对象 print type class 之元类

今日内容概要

  • 面向对象的魔法方法
  • 基于魔法方法的笔试题
  • 元类简介
  • 创建类的两种方式
  • 元类定制类的产生行为
  • 元类定制对象的产生行为
  • 魔法之__new__方法
  • 设计模式简介及单例模式

面向对象的魔法方法

魔术方法的特征:

1.魔术方法都是双下划线开头,双下划线结尾的方法
2.魔术方法都是 python 内部事先定义的,是对象相关行为的底层实现方法
3.魔术方法都是在特定的情况下自动化触发的,一般不会直接去调用。

常用的魔法方法有哪些:

1.__init__
 	对象添加独有数据的时候自动触发
2.___str__
	对象被执行打印操作的时候自动触发   该方法返回什么,就打印什么,并且该方法必须返回一个字符串类型
    
3.__call__  即:对象() 或者 类()()
	对象加括号调用的时候自动触发,该方法返回什么,对象调用之后的返回值就是什么
    
4.__getattr__
	对象点不存在的名字的时候自动触发  该方法返回点不存在的名字就可以得到什么
    
5.__getattribute__
	对象点名字就会自动触发 有它的存在就不会执行上面的__getattr__  (不管点的名字是否存在都会触发)
    
6.__setattr__
	给对象添加或者修改数据的时候自动触发 ( 对象.名字 = 值)
7.__enter__
	当对象被当做with上下文管理操作的开始自动触发 并且该方法返回什么 as后面的变量名就会接收到什么
8.__exit__
	with上下文管理语法运行完毕之后自动触发(子代码结束)

基于魔法方法的笔试题

1.补全下列代码使得运行不报错即可
    class Context:
        pass
    with Context() as f:
        f.do_something()

        
class Context:
     def do_something(self):
         pass
    def __enter__(self):
         return self

    def __exit__(self, exc_type, exc_val, exc_tb):
         pass

 with Context() as f:
     f.do_something()


# 定义字典类型并让字典能够通过句点符的方式操作键值对
class MyDict(dict):
    def __setattr__(self, key, value):
        self[key] = value

    def __getattr__(self,item):
        return self.get(item)
obj = MyDict()
obj.name = '水水'
obj.age = 100
obj.pwd = 'momo'
# print(obj)  # {'name': '水水', 'age': 100, 'pwd': 'momo'}

# print(obj.age) #100
# print(obj.name) # 水水
# print(obj.pwd)   #momo

# print(obj)  #  字典存储的数据{'name': '水水', 'age': 100, 'pwd': 'momo'}
print(obj.__dict__)  #{}字典对象名称空间
print(type(obj))  #<class '__main__.MyDict'>


元类简介

1.在python中一切皆为对象。让我们先定义一个类,然后逐步分析
"""推导步骤1:如何查看数据的数据类型"""
# s1 = 'hello world'  # str()
# l1 = [11, 22, 33, 44]  # list()
# d1 = {'name': 'jason', 'pwd': 123}  # dict()

# print(type(s1))  # <class 'str'>
# print(type(l1))  # <class 'list'>
# print(type(d1))  # <class 'dict'>

"""推导步骤2:其实type方法是用来查看产生对象的类名"""
# class Student:
#     pass
# obj = Student()
# print(type(obj))  # <class '__main__.Student'>

"""推导步骤3:python中一切皆对象 我们好奇type查看类名显示的是什么"""
class Student:
    pass
obj = Student()
print(type(obj))  # <class '__main__.Student'>
print(type(Student))  # <class 'type'>
所有的对象都是实例化或者说调用类而得到的(调用类的过程称为类的实例化),比如对象obj是调用类Student得到的

理解元类:
	1.元类的含义:Meta类就是元类——类的类,在Python中定义类的关键字class也是一个对象,那么实例化class对象的类就是元类。元类的目的就是为了控制类的创建行为。
	2.元类的生成:type作为Python的内建元类,是用来控制类的生成的,class对象就是type实例化生成的。
	3.Python中类的创建方法:因此,Python中创建类的方法其实有两种:(1)使用class关键字;(2)通过type关键字


"""结论:如果一切皆为对象,那么类Student本质也是一个对象,既然所有的对象都是调用类得到的
那么Student必然也是调用了一个类得到的,这个类称为元类(type)  产生类的类"""

image

创建类的两种方式

1.方式一:class 关键字
用class关键字定义的类本身也是一个对象,负责产生该对象的类称之为元类(元类可以简称为类的类),内置的元类为type


class C1:
    user_name = '默默'
    def func(self): pass

print(C1)  #<class '__main__.C1'>
print(C1.user_name)  #默默

2.方式2:利用元类type  type(类名,类的父类,类的名称空间)
StanfordTeache = type( class_name, class_bases, class_dict )


cls = type('c1',(object,),{'name':'水水'})
print(cls)  #<class '__main__.c1'>
print(cls.__dict__)  # 对象名称空间
"""
了解知识:名称空间的产生
1.手动写键值对
    针对绑定方法不好定义
2.内置方法exec
    能够运行字符串类型的代码并产生名称空间
"""

元类定制类的产生行为

"""
推导:
	对象是由类名加括号产生的  __init__
	类是由元类加括号产生的  __init__
"""
自定义一个元类
	1.一个类没有声明自己的元类,默认他的元类就是type,除了使用内置元类type,我们也可以通过继承type来自定义元类,这样我们用 class 关键字生成的元类使用的就是我们自定义的元类
    
    class 类名( 继承的类名, … , metaclass = 自定义的元类名(默认为 type) )
    
步骤分析:
	1、需求分析-----People类,满足类名首字母必须大写,否则无法产生;
	2、首先需要自定义元类 Mymetaclass, 这样 class 类名(metaclass=MyMetaClass)就会对metaclass就会对类名首字母判断
	3、使用 class 关键字创建类,相当于 类名 = Mymeta ( ‘类名’ , (需要继承的基类们,) , { 类体代码执行后的名称空间 } )
	4、调用 Mymetaclass 类—发生"三件事":
	​ 生成一个空对象,调用__init__方法初始化对象,这个对象当做返回
	5、由于 Mymetaclass 类传入了三个参数,所以需要__init__方法,要传入这三个参数以及空对象
	6、在 __init__ 方法中 对传入的参数进行 需求的自定义

# 自定义一个元类:继承type的类也称为元类
class MyMetaClass(type):
    def __init__(cls,what,bases=None,dict=None):
        # print('what',what)
        # print('bases',bases)
        # print('dict',dict)
        if not what.istitle():
            raise TypeError('类的首字母应该都需要大写')
        super().__init__(what,bases,dict) # 重用父类的功能
# 指定类的元类:利用关键字Metaclass指定类的元类
# class myclass(metaclass=MyMetaClass):
    # desc = '元类其实很有趣的,就是有点费脑子'

class Student(metaclass=MyMetaClass):
    info = '老老实实的命名类的名字'

print(Student) # <class '__main__.Student'>
print(Student.__dict__) #对象名称空间

元类定制对象的产生行为

"""
推导
	对象加括号会执行产生该对象类里面的   __call__
	类加括号会执行产生该类的类里面的	__call__
"""

"""给对象添加独有数据的时候 必须采用关键字参数传参"""


class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        # print(args) #()
        # print(kwargs)# {'name': '水水', 'age': 100, 'gender': 'male'}
        if args:
            raise TypeError("这里要求对象独有数据必须按照关键字参数传参!!")
        return super().__call__(*args, **kwargs)  # 重用父类


class Student(metaclass=MyMetaClass):
    def __init__(self, name, age, gender):
        print("__init__")
        self.name = name
        self.age = age
        self.gender = gender


# obj = Student('水水', 100, 'male')  #这里要求对象独有数据必须按照关键字参数传参!!")
obj = Student(name='水水',age=100, gender='male') #{'name': '水水', 'age': 100, 'gender': 'male'}
print(obj.__dict__)

魔法之__new__方法

概念
触发时机: 在实例化对时触发

参数:至少一个cls 接收当前类

返回值:必须返回一个对象实例

作用:实例化对象

注意:实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。

没事别碰这个魔术方法,先触发__new__才会触发__init__

1.在调用类的时候,会首先自动触发 _ _ new _ _方法,执行里面的代码,在触发 init 方法
2.

例子:
class MyMetaClass(type): #只有继承了type类才能称之为一个元类,否则就是一个普通的自定义类
    def __call__(self, *args, **kwargs):
        #1. 产生一个空对象(类似于人的骨架)
        obj = self.__new__(self)
        # 2.d调用__init__给对象添加独有的数据(类似于人添加了血肉)
        self.__init__(obj,*args,**kwargs)
        # 3.返回创建好的对象
# 如果想让一个 对象 可以加括号 调用,那么需要在该对象的类中加入 call 方法,这个对象调用后的返回值就是 call 方法的返回值
        return obj


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


obj = Student('水水')
print(obj.name) # 水水

'__new__可以产生空对象'

设计模式简介及单例模式

1.设计模式
	前人通过大量的验证创建出来解决一些问题的固定高效的方法
2.IT行业
23种:
	创建型
    结构型
    行为型
3.单列模式
定义:确保一个类最多只有一个实例,并提供一个全局访问点(无论类加括号执行多少次,只会产生一个对象)
目的:
	当类中有很多非常强大的方法,我们在程序中很多地方都需要使用
    1.优点
        1.1.单例模式可以保证内存里只有一个实例,减少了内存的开销。
        1.2.可以避免对资源的多重占用。
        1.3.单例模式设置全局访问点,可以优化和共享资源的访问。
     2.缺点
        2.1.单例模式一般没有接口,扩展困难。
        2.2.单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则

标签:__,python,元类,面向对象,对象,print,type,class,之元类
From: https://www.cnblogs.com/qiguanfusu/p/16870612.html

相关文章

  • Python 生成MySQL数据库的表结构到word文档
    原理:读取系统表的数据,调用python-docx库生成word文档。importpymysqlfromdocximportDocumentfromdocx.sharedimportInchesdocument=Document()document.a......
  • QProcess 调用.py脚本(windows + python 环境)
    1QProcessp;2QStringListargs1;3args1.append("demo.py");//设置py脚本4p.setWorkingDirectory("d:/demo/");//设置py脚本所在目录5p......
  • Python driver 设置
    options=webdriver.ChromeOptions()#不加载图片,加快访问速度options.add_experimental_option("prefs",{"profile.managed_default_content_settings.images":2})#......
  • Python基础之面向对象:7、面向对象之魔法方法
    目录面向对象之魔法方法一、魔法方法的概念二、常用魔法方法1、__init__2、__str__3、__call__4、__getattr__5、__getattribute__6、__setattr__7、__enter......
  • python 面向对象之元类
    python面向对象之元类type方法的应用1.查看数据类型s1='helloworld'#str()l1=[11,22,33,44]#list()d1={'name':'jason','pwd':123}#dict()t1......
  • Python基础之面向对象:8、面向对象之元类
    目录面向对象之元类一、什么是元类二、元类推导流程三、创建类的方式方式一:方式二:四、元类定制类的产生行为五、元类定制对象的产生行为六、元类之双下new面向对象之元类......
  • python import
    fromtest2import*import导入和fromimport导入,在内存上没有差别,都需要从头到尾全部编译一遍,并加载到内存中。这里如果在test2中定义__all__=['func1',....],这里限制了......
  • IOU计算-纯python
    iou计算代码,纯pythonfrom:https://blog.csdn.net/leviopku/article/details/81629492#!/usr/bin/envpython#encoding:utf-8defcompute_iou(rec1,rec2):......
  • Python学习笔记3
    Python学习笔记3       Python中的True和Falsepath=os.path.join('a','b')print(path)#a\bmessages=[]ifmessages==False:  print('[]就是False')m......
  • oop面向对象
    面向对象OOP面向过程&面向对象面向过程思想步骤清晰简单,第一步做什么,第二步做什么...面对过程适合处理一些较为简单的问题面向对象思想物以类聚,分类的思维模......