• Day 22 绑定方法和非绑定方法/isinstance/issubclass/反射/魔法方法/单例模式


    类和对象的绑定方法与非绑定方法

    类中定义的方法大致可以分成两类:绑定方法和非绑定方法.其中绑定方法又可以分为对象的绑定方法和类的绑定方法

    绑定方法

    对象的绑定方法

    在类中没有被任何装饰器修饰的方法就是对象的绑定方法

    对象的绑定方法的特殊之处在于调用方法时会自动将当前对象传给方法的第一个参数

    类的绑定方法

    类中使用 @classmethod 装饰器修饰的方法就是绑定到类的方法

    类的绑定方法的特殊之处在于利用类名调用方法时,会自动将当前类传给方法的第一个参数

    class Foo:
        @classmethod
        def foo(cls):
            print('这是类的绑定方法')
    
    
    Foo.foo()
    print(Foo.foo)
    
    这是类的绑定方法
    <bound method Foo.foo of <class '__main__.Foo'>>
    

    通过对象也可以调用,只不过默认传递的第一个参数还是这个对象对应的类

    非绑定方法

    类中使用 @staticmethod 装饰器修饰的方法就是非绑定方法

    这类方法和普通定义的函数没有区别,不与类或对象绑定,谁都可以调用,并且没有自动传入的值

    import uuid
    
    
    class Student:
        def __init__(self, name, age, gender):
            self.name = name
            self.age = age
            self.gender = gender
            self.stu_id = self.creat_id()
    
        @staticmethod
        def creat_id():
            stu_id = uuid.uuid1()
            return stu_id
    
    
    stu1 = Student('Tiny', 18, 'male')
    print(stu1.creat_id())
    print(stu1.stu_id)
    print(Student.creat_id())
    
    b082496d-ecc0-11e9-afa2-005056c00008
    b082496c-ecc0-11e9-9089-005056c00008
    b082496e-ecc0-11e9-ab2d-005056c00008
    

    小结

    如果函数体代码需要用外部传入的类,那么就要把函数定义成绑定类的方法

    如果函数体代码需要用外部传入的对象,那么就要把函数定义成绑定对象的方法

    如果函数体代码既不需要从外部传入类,也不需要从外部传入对象,则应该将该函数定义成非绑定方法

    isinstance

    可以传入两个参数,用于判断参数一是否是参数二的一个实例

    class Foo:
        pass
    
    
    class Soo(Foo):
        pass
    
    
    print(isinstance(Soo(), Foo))
    

    True

    issubclass

    可以传入两个参数,用于判断参数1是否是参数二的子类

    class Foo:
        pass
    
    
    class Soo(Foo):
        pass
    
    
    print(issubclass(Soo, Foo))
    

    True

    反射

    反射就是通过字符串来操作类或者对象的属性

    • hasattr: 通过字符串,判断该字符串是否是类或者对象的属性
    • getattr: 通过字符串,获取类或者对象的属性
    • setattr: 通过字符串,设置类或者对象的属性
    • delattr: 通过字符串,删除类或者对象的属性
    class People:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    # hasattr
    p = People('Tiny', 18)
    print(hasattr(p, 'name'))
    
    # getattr
    print(getattr(p, 'gender', 'male'))
    print(p.__dict__)
    print(hasattr(p, 'gender'))
    
    # setattr
    setattr(p, 'gender', 'male')
    print(p.__dict__)
    print(hasattr(p, 'gender'))
    
    # delattr
    delattr(p, 'gender')
    print(p.__dict__)
    print(hasattr(p, 'gender'))
    

    魔法方法

    凡是类内部定义,以__开头__结尾的方法都称之为魔法方法,又称为类的内置方法

    魔法方法会在某些条件成立时触发

    '''
    __init__: 在调用类的时候触发
    __str__: 在打印对象时触发
    __del__: 对象被销毁前执行该方法
    __getattr__: 会在 对象.属性 时,属性没有的情况下触发
    __setattr__: 会在 对象.属性 = 属性值 时触发
    __call__: 会在对象被调用的时候触发
    __new__: 会在__init__执行前触发
    '''
    
    class MagicalMethod:
        def __init__(self):
            print('调用类的时候触发我')
    
        def __str__(self):
            print('打印对象的时候触发我')
            return '必须要有返回值哦'
    
        def __del__(self):
            print('对象销毁前触发我')
            print(self)
    
        def __getattr__(self, item):
            print(item)
            return '没返回值默认返回None'
    
        def __setattr__(self, key, value):
            print(key, value)
    
        def __call__(self, *args, **kwargs):
            print('对象被调用时触发我')
    
        # def __new__(cls):
        #     print('在执行__init__前调用我')
    
    
    m = MagicalMethod()
    print(m.x)
    m.x = 1
    m()
    

    单例模式

    class Student:
        __instance = None
    
        # @classmethod
        # def singleton(cls, name, age):
        #     if not cls.__instance:
        #         cls.__instance = cls(name, age)
        #     return cls.__instance
    
        def __new__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = super().__new__(cls)
            return cls.__instance
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    stu1 = Student('Tiny', 18)
    stu2 = Student('nick', 18)
    print(stu1)
    print(stu2)
    print(stu1.name)
    print(stu2.name)
    
    # stu1 = Student.singleton('Tiny', 18)
    # stu2 = Student.singleton('Nick', 18)
    # print(stu1)
    # # print(stu2)
    # print(stu1.name)
    # # print(stu2.name)
    
    <__main__.Student object at 0x004563B0>
    <__main__.Student object at 0x004563B0>
    nick
    nick
    
  • 相关阅读:
    LeetCode 1110. Delete Nodes And Return Forest
    LeetCode 473. Matchsticks to Square
    LeetCode 886. Possible Bipartition
    LeetCode 737. Sentence Similarity II
    LeetCode 734. Sentence Similarity
    LeetCode 491. Increasing Subsequences
    LeetCode 1020. Number of Enclaves
    LeetCode 531. Lonely Pixel I
    LeetCode 1091. Shortest Path in Binary Matrix
    LeetCode 590. N-ary Tree Postorder Traversal
  • 原文地址:https://www.cnblogs.com/2222bai/p/11663463.html
Copyright © 2020-2023  润新知