首页 > 其他分享 >面向对象4

面向对象4

时间:2022-11-08 21:03:50浏览次数:39  
标签:__ obj 对象 Pattern self 面向对象 print

面向对象4

目录

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

面向对象的魔法方法

1.魔法方法的介绍

1.1其实就是类中定义的对双下方法的一个别名

1.2 之所以会叫魔法方法是因为这些方法都是到达某个条件自动触发,无需调用

​ 例如:init__方法,在实例化对象的时候,类加括号,在括号里加一些数据的时候,它会自动调用这个方法

2.魔法方法的学习

2.1代码演练

class MyClass(object):
    def __init__(self, name):
        # print('__init__方法')
        self.name = name


    def __str__(self):
        """
        对象被执行打印操作时候会自动触发
          该方法必须返回一个字符串
          返回什么字符串打印对象之后就展示什么字符串
        """
        # print('__str__方法')
        return ''

    def __call__(self, *args, **kwargs):
        # print('__call__方法')
        # print(args)
        # print(kwargs)
        pass


    def __getattr__(self, item):
        """
        当对象获取一个不存在的属性名时,自动触发
        该方法返回什么,对象获取不存在的属性名就会得到什么
        形参item就是对象想要获取的不存在的属性名
        """
        print('__getattr__方法')
        return 123
    def __setattr__(self, key, value):
        """
        对象操作属性值的时候自动触发
        有  对象.属性 = 属性值
        """
        print('__setattr__')  # __setattr__
        print(key)  # name
        print(value)  # tom

    def __del__(self):
        """对象在被删除(主动 被动)的时候自动触发"""
        # print('__del__')
        pass

    def __getattribute__(self, item):
        """
        对象获取属性的时候自动触发 无论这个属性在不在
        当类中既有__getattr__又有__getattribute__的时候 只会走后者
        """
        return super().__getattribute__(item)  # 简便写法

    def __enter__(self):
        """对象被with语法执行的时候自动触发 该方法放回什么 as关键字 后的f就能得到什么 """
        print('__enter__')

    def __exit__(self, exc_type, exc_val, exc_tb):
        """对象被with语法执行并执行完with子代码之后 自动触发"""
        print('__exit__')





obj = MyClass('jason')
# obj(1, 2, 3, name= 'kerry')
print(obj)
# obj.name = 'tom'
print(obj.age)
print(obj.__dict__)
with obj as f:
    print(f)

2.2文字追加说明

1.双下init方法的结果:<__main__.MyClass object at 0x000001E4FD544B80>
2.双下 str方法的结果:TypeError: __str__ returned non-string (type NoneType)
    双下 str在对象执行打印操作的时候就会自动触发,并且必须要放回一个字符串数据,否则报错
    这个方法的目的是为了在我们操作打印的时候,可以做一些提示信息,并做一些更改
3.双下call方法,在类里面定义一个双下call,这个类在将来产生的对象,就会有加括号调用的功能
    如果不写的话,就不能使用加括号调用
    然后触发双下call的运行,并且还可以加参数
    那么这个对象既然拥有的对象的功能还拥有了函数的功能
4.双下getattr方法,当对象获取一个不存在的属性名时,自动触发
    如果放回一个 123的时候。那么在这个属性名不存在的时候,它会除非返回123,就是在不存在的时候返回是什么,这个对象.属性名
    就会得到什么
5.双下 setattr方法,对象操作属性值的时候自动触发
6.双下 del方法,对象在被删除(主动 被动)的时候自动触发
   在对象执行的时候就会自动触发
   在整个运行结束的时候,整个空间所有的东西会被删除清空,那么这个时候也会被触发
7.双下getattribule,对象获取属性的时候时自动触发  无论这个属性存不存在
   当类中既有双下getattr又有双下getattribute的时候 只会走后者
8.双下enter方法,对象被with语法执行的时候自动触发 该方法放回什么 as关键字 后的f就能得到什么
9.双下exit方法,对象被with语法执行并执行完with子代码之后 自动触发

2.3额外补充知识

额外补充:
print(obj.__dict__)  # {}
obj.name(当对象获取一个不存字的属性名时,自动触发)的时候不存在,但是我们明明在双下init中存在name,这是为什么呢??
    首先,我们可以使用的双下的那些方法是因为继承的父类里面的双下方法
    然后我们在自己的类里面写了双下方法,那么就不会执行父类里面的双下方法了,现在我们知识打印了以下,并没有讲数据放入对象的独有空间里面,所以就是没有
    那么现在就是,我们把原来的方法重新写了,不能再使用到原来的方法了,子类继承了父类,又把里面的方法重新写了,覆盖了父类的方法
    如果想再次使用父类里面的原来的那个方法那么就使用:super().__setattr__(key, value)  将该有的东西传入,self可以不传

基于魔法方法的面试题

'''补全以下代码,执行之后不会报错'''
class Context:
    # 补充的代码
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        pass
    def do_something(self):
        pass
with Context() as f:  # Context()是一个对象,对象放到类里面,那么就靠考虑它会干什么事情
    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 = 'jason'
        obj.pwd = 18
        obj.hobby = 'read'
        # print(obj)
        print(obj.name)
        print(obj.pwd)
        print(obj.hobby)
         print(obj)
        # print(obj)  # 字典存储的数据  {}
        # print(obj.__dict__)  # 字典对象名称空间  {'name': 'jason'}

元类简介

 s1 = '哈哈哈 今天下午终于可以敲代码了!!!'
 l2 = [60, 80, 100, 120, 150, 200]
 d = {'name': '死给我看', 'age': 18}
 print(type(s1))  # <class 'str'>
 print(type(l2))  # <class 'list'>
 print(type(d))  # <class 'dict'>
"""
基础阶段我们使用type来查找数据的数据类型
但是学了面向对象之后 发现查看的不是数据类型 而是数据所属的类
我们定义的数据类型 其实本质还是通过各个类产生了对象
    class str:
        pass
    h = 'hello' 等于 str('hello')
我们也可以理解为type用于查看产生当前对象的类是谁
"""
class MyClass:
    pass
obj = MyClass()
print(type(obj))  # 查看产生对象obj的类:<class '__main__.MyClass'>
print(type(MyClass))  # 查看产生对象MyClass的类:<class 'type'>
"""
通过上述推导 得出结论 自定义的类都是由type类产生的
我们将产生类的类称之为 '元类'
"""

创建类的两种方式

# 方式1:使用关键字class
class Teacher:
    school_name = '老女儿'
    def func1(self):pass
print(Teacher)
print(Teacher.__dict__)
# 方式2:利用元类type  type(类名,类的父类,类的名称空间)
cls = type('Student', (object,), {'name':'jason'})
print(cls)
print(cls.__dict__)
"""
了解知识:名称空间的产生
1.手动写键值对
    针对绑定方法不好定义
2.内置方法exec
    能够运行字符串类型的代码并产生名称空间
"""

元类定制类的产生行为

class MyMetaClass(type):
    pass
"""只有继承了type的类才可以称之为是元类"""
class MyClass(metaclass=MyMetaClass):
    pass
'''
metaclass是使用元类的关键字
如果想要切换产生类的元类不能使用继承 必须使用关键字metaclass去声明
MyClass是由MyMetaClass负责产生的
类中的__init__用于实例化对象
元类中__init__用于实例化类
'''

class MyMetaClass(type):
    # def __init__(self):  # 报错,现在继承的是type,type里面有__init__,这个时候其实已经把元类中的__init__给替换掉了,元类里的__init__就不能在使用了,只要重写了父类,在最后都得调用回去,super().__init__(what, bases, dict)
    def __init__(self,what, bases=None, dict=None):
        # print('别磕睡')
        # print('what', what)  类名 MyClass
        # print('bases', bases) 类的父类
        # print('dict', dict) 类的名称空间
        if not what.istitle():
            # print('首字母必须大写')
            raise Exception('首字母必须大写')
        super().__init__(what, bases, dict)
"""只有继承了type的类才可以称之为是元类"""

# class Myclass(metaclass=MyMetaClass):
#     pass
class aaa(metaclass=MyMetaClass):
    pass

元类定制对象的产生行为

元类不仅可以控制类的产生过程,还可以控制对象的产生
1.对象加括号执行产生该对象类里面的双下call
2.类加括号执行产生该类的元类里面的双下call

class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        print('__call__')
        if args:
            raise Exception('必须用关键字参数传参')
        super().__call__(*args, **kwargs)

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

obj = MyClass('jason', 18)
obj = MyClass(name='jason', age=38)
'''
参数是怎么传入进去的?
    参数给予双下call,然后在双下call中会调用双下init
'''
"""
总结:
如果我们想高度定制对象的产生过程
	可以操作元类里面的__call__
如果我们想高度定制类的产生过程
	可以操作元类里面的__init__
"""

魔法方式之双下new

class MyMetaClass(type):
    def __call__(self, *args, **kwargs):
        # 1.产生一个空对象(骨架)
        obj = self.__new__(self)
        # 2.调用__init__给对象添加独有的数据(血肉)
        self.__init__(obj,*args, **kwargs)
        # 3.返回创建好的对象
        return obj


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

obj = Student('jason')
print(obj.name)
"""
__new__可以产生空对象
"""

设计模式简介

1.如何理解设计模式

在IT行业有很多前人通过大量的验证创建出来解决一些问题的固定高效方法

2.设计模式(23种)

工厂模式(Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
建造者模式(Builder Pattern)
原型模式(Prototype Pattern)
工厂模式(Factory Pattern)
抽象工厂模式(Abstract Factory Pattern)
单例模式(Singleton Pattern)
建造者模式(Builder Pattern)
原型模式(Prototype Pattern)
责任链模式(Chain of Responsibility Pattern)
命令模式(Command Pattern)
解释器模式(Interpreter Pattern)
迭代器模式(Iterator Pattern)
中介者模式(Mediator Pattern)
备忘录模式(Memento Pattern)
观察者模式(Observer Pattern)
状态模式(State Pattern)
空对象模式(Null Object Pattern)
策略模式(Strategy Pattern)
模板模式(Template Pattern)
访问者模式(Visitor Pattern)
MVC 模式(MVC Pattern)
业务代表模式(Business Delegate Pattern)
组合实体模式(Composite Entity Pattern)
数据访问对象模式(Data Access Object Pattern)
前端控制器模式(Front Controller Pattern)
拦截过滤器模式(Intercepting Filter Pattern)
服务定位器模式(Service Locator Pattern)
传输对象模式(Transfer Object Pattern)

3.设计模式分类

创建型  结构型  行为型

4.设计模式之单例模式

类加括号调用多次只允许产生一个对象
class MyClass:
    pass

obj1 = MyClass()
obj2 = MyClass()
obj3 = MyClass()
print(id(obj1), id(obj2), id(obj3))  # 2263190030944 2263190494080 2263189844464

'''
正常情况下 类名只要加括号实例化产生对象 执行几次就会产生几个不同的对象
'''

'''
有时候我们不希望类频繁的产生不同的对象
  	类中有很多很好用的方法 程序很多地方都需要使用(通过对象调用)
  	如果产生的地方特别多 那么会浪费一定的内存空间 所以需要使用单例
'''
方式1:使用元类干预对象的创建过程
    class MyMeTaClass(type):
        # 记录类是否已经创建了对象
        instance = None

        def __call__(self, *args, **kwargs):
            if self.instance:
                return self.instance
            # 获取空对象
            obj = super().__call__(*args, **kwargs)
            # 保存对象
            self.instance = obj
            # 返回空对象
            return obj

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

                obj1 = Single('jason')
                obj2 = Single('kevin')
                obj3 = Single('tony')
                print(id(obj1), id(obj2), id(obj3))
                print(obj1.name)
                print(obj2.name)
                print(obj3.name)

标签:__,obj,对象,Pattern,self,面向对象,print
From: https://www.cnblogs.com/zjl248/p/16871167.html

相关文章

  • 面向对象高级
    目录面向对象高级今日内容概要今日内容详细面向对象的魔法方法魔法方法笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new设计......
  • 面向对象魔法方法、元类
    1.面向对象的魔法方法魔法方法:类中定义的双下方法都称为魔法方法使用方法:不需要认为调用,在特定条件下自动触发运行eg:__init__是创建对象之后自动触发给对象添加独有......
  • 面向对象的魔法方法及元类
    魔法方法 类中定义的双下方法都可以叫做魔法方法,其特定情况下可以自动触发运行1.__init__对象添加独有数据的时候自动触发2.__str__对象执行打印操作时自动触发......
  • Python——面向对象(魔法方法、元类)
    Python——面向对象(魔法方法、元类)魔法方法'''魔法方法: 类中定义的双下方法都称为魔法方法 不需要人为调用在特定的条件下回自动触发运行 eg:__init__创建空......
  • 面向对象之魔法方法及元类
    昨日内容回顾类的派生的应用在需要对原有的方法进行个性化扩展时,需要应用到方法的派生。在进行派生时,需要先定位到需要派生的的功能,添加个性化的功能后,使用super调用......
  • 面向对象之魔法方法/元类
    面向对象的魔法方法classC1:name='张三丰'age=18def__init__(self,name):#对象添加数据或改变数据时自动触发print('__init__......
  • 面向对象的魔法方法、元类定制类与对象的产生行为
    今日内容回顾目录今日内容回顾面向对象的魔法方法魔法方法笔试题元类简介创键类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new设计模式简介面......
  • 面向对象4
    今日内容详细面向对象面对对象的魔法方法魔法方法:类中定义的双下方法都称为魔法方法不需要人为调用在特定的条件下会自动触发运行eg:__init__创建空对象之后自动触......
  • 面向对象的魔法方法与元类
    面向对象的魔法方法与元类面向对象的魔法方法魔法方法就是在类中定义的双下方法,它不需要人为调用,在特定的条件下会自动触发运行1.__init__对象添加独有数据的时候会......
  • 面向对象魔法方法及元类
    内容概要面向对象的魔法方法基于魔法方法的笔试题元类简介创建类的两种方式元类定制类的产生行为元类定制对象的产生行为魔法方法之双下new方法设......