首页 > 其他分享 >面向对象之魔法方法/元类

面向对象之魔法方法/元类

时间:2022-11-08 20:16:13浏览次数:49  
标签:__ name 对象 self 魔法 元类 面向对象 print type

面向对象的魔法方法

class C1:
    name = '张三丰'
    age = 18

    def __init__(self, name):
        # 对象添加数据或改变数据时自动触发
        print('__init__')

    def __str__(self):
        print('__str__')
        return f'{self.name}'
        # 当对象被执行打印操作时执行,并必须要有返回值

    def __call__(self, *args, **kwargs):
        print('__call__')
        return f'{self.name}'
        # 当对象加括号调用的时候会自动触发

    def __getattr__(self, item):
        print(f'{item},不存在')
        # 对象在调用没有的数据值时会自动触发

    # def __getattribute__(self, item):
    #     print('__getattribute__')
    #     # 当对象获取数据的时候自动触发
    #     # 缺点 即使 对象有该数据 也无法拿到


    def __setattr__(self, key, value):
        print('__setattr__')

        # 当对象 添加值 或者更改值的时候都会自动触发
        # obj.name = '111' 当有对象名称赋值时就会触发

    def __enter__(self):
        print('__enter__')
        # 当对象跟with语法一起使用时 会自动触发,并且该方法返回什么,as后面就可以接收到什么
        return '333'

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')
        # 当对象参与with语法结束后 自动触发




ojb1 = C1('moon')
with ojb1 as f:
    print(f)
'''
ojb1 = C1('moon')
# 给对象添加或更改 独有的数据时,会自动执行__init__里面的代码

print(ojb1)
# 当执行打印对象的操作时,会自动触发__str__函数

a1 = ojb1()
# 对象加括号为自动触发_call__里面的代码,如果有返回值,则可以用变量接收

print(a1)
# a1 接收到了__call__返回的值

# ojb1.hhh
# 当对象.一个不存在的名字是 自动触发 __getattr__函数

ojb1.age = '周芷若'
# 有赋值符号时 触发 __setattr__函数
'''

魔法方法小练习

# 补全下列代码使的运行不报错
# class Context:
#     pass
# with Context() as f:
#     f.do_something()


# 当对象遇到with方法是需要用到__enter__和__exit__才可以


class Context:
    def do_something(self):
        print('123')

    def __enter__(self):
        return self
        #需要返回给 f 赋值
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass


with Context() as f:
    f.do_something()
    # f 是什么 f是 __enter__返回的内容
    # 对象调用一个方法,对象本身没有 就需要产生对象的类中有
    
    

2.自定义字典类型并让字典能够通过句点符的方式操作键值对

class Mydict(dict):
    def __setattr__(self, key, value):
        # 当使用 obj.name = 'moon' 语法时自动触发
        self[key] = value
        # 给对象添加 键值对

    def __getattr__(self, item):
        # 当使用 obj.name 语法时触发,因为对象是自动,没有自己的名称空间所以你.什么都会触发这个
        return self.get(item)
        # 手动 获取 字典内的 值

obj = Mydict()
obj.name = 'moon'
obj.age = 17
print(obj)
print(obj.name)

'''
思路:首先想到要用类去继承这个字典,然后添加额外的操作
'''

元类简介

''' 推导步骤1:如何查看数据的数据类型 '''
# s1 = 'hello world'  # str()
# l1 = [11, 22, 33, 44]  # list()
# d1 = {'name': 'jason', 'pwd': 123}  # dict()
# t1 = (11, 22, 33, 44)  # tuple()
# print(type(s1))  # <class 'str'>
# print(type(l1))  # <class 'list'>
# print(type(d1))  # <class 'dict'>
# print(type(t1))  # <class 'tuple'>
"""推导步骤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'>
class A:pass
class B:pass
print(type(A), type(B))
"""结论:我们定义的类其实都是由type类产生的>>>:元类(产生类的类)"""

产生类的两种方式

1. 关键词 class 创建 
   class C1:
      name = 'moon'
      
2. 利用元类 type 来创建类
   type(类名,(是否有父类),{名称空间})
   type('C1',(),{'name':'moon'})
    
a1 = C1()
# 生成一个对象
a2 = type('C1',(),{'name':'moon'})()
# 也是生成一个对象 
print(a1.name)
print(a2.name)
print(type(a1)) # <class '__main__.C1'>
print(type(a2)) # <class '__main__.C1'>
# 类型也都是一样的

'''
所以得出结论,利用class 创建 类 或者 type(类名,(是否有父类),{名称空间}) 
都是一样的 2种创建类的方法
'''

元类定制类的方法

1.首先我们得到 类是由元类 产生的, 元类是 type
2.如果我们想控制类的产生,那就要想办法 重新 产生类的过程
3.类是通过元类里面的__init__方法产生的
4.那么我们只需要改变元类的这个方法就可以了


class Mytype(type):
  # 重新定义一个元类
    def __init__(self, what, bases=None, dict=None):
      # 重新__init__方法,添加需求,当what参数满足要求后,才执行__init__
        if not what.istitle():
            raise TypeError('命名错误,首字母需要大写')
        super().__init__(what, bases, dict)


class V1(metaclass=Mytype):
  # 用关键词 metaclass=  来更改产生类的元类
    pass
  
  '''
  这样就达到了我们的需求
  元类定制类的方法:就是重写元类中产生类的方法,然后增加控制
  在创建新的类时,更改类的元类
  '''

元类定制对象的方法


"""
推导
	对象加括号会执行产生该对象类里面的   __call__
	类加括号会执行产生该类的类里面的	__call__
"""
"""给对象添加独有数据的时候 必须采用关键字参数传参"""

class Mytype(type):
    def __call__(self, *args, **kwargs):
        # 通过__call__方法来生成对象的,所以重写此方法
        
        # 1.产生一个空对象(骨架)
        # 2.调用__init__给对象添加独有的数据(血肉)
        # 3.返回创建好的对象
        # print(args)  # ('jason', 18, 'male')
        # print(kwargs)  # {}
        if args:
            raise TypeError('必须按照关键词传参')
        return super().__call__(*args, **kwargs)
        # 通过条件后,在原封不动的调用__call__方法

class C1(metaclass=Mytype):
    def __init__(self,name,age):
        self.name = name
        self.age = age


res = C1(name = 'moon',age = 18)
# 这里的数据 是先交给了元类里面的__call__执行了一遍,才能到__init__

魔法方法之双下new

class Mytype(type):
    def __call__(self, *args, **kwargs):
        res = self.__new__(self)
        # __call__方法是创建对象的
        # __new__产生一个空对象
        self.__init__(res, *args, **kwargs)
        # 调用__init__给空对象添加独有属性
        return res
        # 然后把这个对象返还 这就是产生对象的流程

class C1(metaclass=Mytype):
    def __init__(self,name,age):
        # __init__只是定义对象独有数据,并不产生对象
        self.name = name
        self.age = age


res = C1('moon', 18)
print(res.age)
# 这里的数据 是先交给了元类里面的__call__执行了一遍,才能到__init__

设计模式简介

1.设计模式
	前人通过大量的验证创建出来解决一些问题的固定高效方法
2.IT行业
	23种
        创建型
        结构型
        行为型
 	ps:课下感兴趣可以简单看看
3.单例模式
	类加括号无论执行多少次永远只会产生一个对象
 	目的:
        当类中有很多非常强大的方法 我们在程序中很多地方都需要使用
        如果不做单例 会产生很多无用的对象浪费存储空间
        我们想着使用单例模式 整个程序就用一个对象

标签:__,name,对象,self,魔法,元类,面向对象,print,type
From: https://www.cnblogs.com/moongodnnn/p/16870991.html

相关文章

  • 面向对象的魔法方法、元类定制类与对象的产生行为
    今日内容回顾目录今日内容回顾面向对象的魔法方法魔法方法笔试题元类简介创键类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new设计模式简介面......
  • 面向对象4
    今日内容详细面向对象面对对象的魔法方法魔法方法:类中定义的双下方法都称为魔法方法不需要人为调用在特定的条件下会自动触发运行eg:__init__创建空对象之后自动触......
  • 面向对象的魔法方法与元类
    面向对象的魔法方法与元类面向对象的魔法方法魔法方法就是在类中定义的双下方法,它不需要人为调用,在特定的条件下会自动触发运行1.__init__对象添加独有数据的时候会......
  • 元类、魔法方法(魔术方法)
    目录今日内容概要今日内容详细面向对象的魔法方法魔法方法笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new设计模式简介作业......
  • 面向对象魔法方法及元类
    内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new方法设......
  • 面向对象的魔法方法、魔法方法笔试题、元类简介、创建类的两种方式、元类定制类的产生
    面向对象的魔法方法魔法方法:类中定义的双下方法都称为魔法方法 不需要人为调用在特定的条件下回自动触发运行 eg:__init__创建空对象之后自动触发给对象添加独有的数......
  • 面向对象编程(四)
    面向对象编程(四)一、面向对象的魔法方法1.魔法方法简介在类中,有一些内置好的特定的方法,方法名是“__xx__”,在进行特定的操作时会被调用,这些方法被称为魔法方法,不需......
  • 面向对象之元类、魔法方法
    今日内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为袁磊定制对象的产生行为魔法方法之双侠new方法设计模式简......
  • 面向对象的魔法方法、元类
    目录一、面向对象的魔法方法1.魔法方法介绍(1)__init__(2)__str__(3)__call__(4)__getattr__(5)__getattribute__(6)__setattr__(7)__enter__(8)__exit__(9)__del__2.魔法方法笔试题1)补全下列......
  • python(面向对象之元类,魔法方法)
    今日内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法之__new__方法设计模式简介及单......