• Python 面向对象编程(进阶部分)


    静态方法:

    通过 @staticmethod 装饰器即可把其装饰的方法变为一个静态方法。普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

    示例:

    class Dog(object):
    
        def __init__(self, name):
            self.name = name
    
        @staticmethod
        def eat_static(food):                  # 不能传入 self 否则会报错
            print(' is eating %s' % food)
    
        def eat(self, food):
            print('%s is eating %s' % (self.name, food))
    
    
    d = Dog('A dog')
    d.eat_static('bone')                        # 调用静态方法
    d.eat('bone')

    输出结果:

    is eating bone
    A dog is eating bone

     

    类方法:

    类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量

    示例:

    class Dog(object):
        name = 'Dog'                                # 类变量
    
        def __init__(self, name):
            self.name = name
    
        @classmethod
        def eat_class(cls, food):                   # 不能传入 self 否则会报错
            print('%s is eating %s' % (cls.name, food))
    
        def eat(self, food):
            print('%s is eating %s' % (self.name, food))
    
    
    d = Dog('A dog')
    d.eat_class('bone')                             # 调用类方法
    d.eat('bone')

    输出结果:

    Dog is eating bone
    A dog is eating bone

     

    属性方法:

    属性方法的作用就是通过 @property 把一个方法变成一个静态属性

    简单使用示例:

    class Dog(object):
    
        def __init__(self, name):
            self.name = name
    
        @property
        def eat(self):
            print("%s is eating" % self.name)
    
    
    d = Dog("A dog")
    d.eat                                           # 调用属性(无法直接传参数),加括号会报错

    输出结果:

    A dog is eating

     

    给属性方法赋值

    示例:

    class Dog(object):
    
        def __init__(self, name):
            self.name = name
    
        @property
        def eat(self):
            print("%s is eating" % self.name)
    
        @eat.setter
        def eat(self, food):                        # 当给属性方法赋值时,调用这个方法
            print('The food is %s' % food)
    
    
    d = Dog("A dog")
    d.eat
    d.eat = 'bone'

    输出结果:

    A dog is eating
    The food is bone

     

    如果希望属性方法有参数,需要将参数存为类变量

    示例:

    class Dog(object):
    
        def __init__(self, name):
            self.name = name
            self.__food = None
    
        @property
        def eat(self):
            print("%s is eating %s" % (self.name, self.__food))
    
        @eat.setter
        def eat(self, food):
            print('The food is %s' % food)
            self.__food = food
    
    
    d = Dog("A dog")
    d.eat
    d.eat = 'bone'
    d.eat

    输出结果:

    A dog is eating None
    The food is bone
    A dog is eating bone

    删除属性方法只需在上面函数的基础上再写一个:

    @eat.deleter
        def eat(self):
            del self.__food

    之后再调用 self.__food属性时就会报错,已经找不到了。

    类的特殊成员方法:

    1.__doc__:表示类的描述信息

    class Dog(object):
        '''这个类是用来描述狗这个对象的'''
        def __init__(self):
            pass
    
    
    print(Dog.__doc__)

    输出结果:

    这个类是用来描述狗这个对象的

    2.__module__、 __class__

             __module__ 表示当前操作的对象在那个模块

        __class__     表示当前操作的对象的类是什么

    libaa.py:

    class C(object):
    
        def __init__(self, name):
            self.name = name

    index.py:

    from lib.aa import C
    
    obj = C('name')
    print(obj.__module__)
    print(obj.__class__)

    输出结果:

    lib.aa

    <class ’lib.aa.C’>

    3.__init__:构造方法

    4.__del__:析构函数

    5.__call__:对象后面加括号,触发执行

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    
    obj = Foo()         # 执行 __init__
    obj()               # 执行 __call__
    Foo()()

    输出结果:

    __call__
    __call__

    6__dict__

    通过类调用:查看类里的所有属性(不包括实例里的)

    通过实例调用:查看实例里的所有属性(不包括类里的)

    通过字典储存类中所有属性,绑定动态属性时也会在字典中添加相应项。占用内存较大,当存在大量实例时会占用大量资源,可以通过 '__slots__' 解决 <--点击查看

    class Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
            print('__call__')
    
    
    obj = Foo()
    print(Foo.__dict__)
    print(obj.__dict__)

    输出结果:

    {'__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__module__': '__main__', '__init__': <function Foo.__init__ at 0x000001CED095D378>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__doc__': None, '__call__': <function Foo.__call__ at 0x000001CED3A9B510>}
    {}

    7.__str__:如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值

    不使用__str__时:

    class Foo(object):
    
        def __init__(self, name):
            self.name = name
    
    
    obj = Foo('A obj')
    print(obj)

    输出结果:

    <__main__.Foo object at 0x0000024051A5F0F0>

    如果加上__str__:

    class Foo(object):
    
        def __init__(self, name):
            self.name = name
    
        def __str__(self):
            return '<obj:%s>' % self.name
    
    
    obj = Foo('obj name')
    print(obj)

    输出结果:

    <obj:A obj>

    8.__getitem__、__setitem__、__delitem__

    用于索引操作,如字典。以上分别表示获取、设置、删除数据

    class Foo(object):
    
        def __getitem__(self, key):
            print('__getitem__', key)
    
        def __setitem__(self, key, value):
            print('__setitem__', key, value)
    
        def __delitem__(self, key):
            print('__delitem__', key)
    
    
    obj = Foo()
    
    result = obj['k1']      # 自动触发执行 __getitem__
    obj['k2'] = 'name'      # 自动触发执行 __setitem__
    del obj['k1']           # 自动触发执行 __delitem__

    输出结果:

    __getitem__ k1
    __setitem__ k2 name
    __delitem__ k1

    9.__new__ 、__metaclass__

    先看一段代码:

    class Foo(object):
    
        def __init__(self, name):
            self.name = name
    
    
    f = Foo("name")
    print(type(f))
    print(type(Foo))

    输出结果:

    <class '__main__.Foo'>
    <class 'type'>

    所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建

    类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

    类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

    自定义元类:

    class MyType(type):
        def __init__(cls, *args, **kwargs):
    
            print("Mytype __init__", *args, **kwargs)
    
        def __call__(cls, *args, **kwargs):
            print("Mytype __call__", *args, **kwargs)
            obj = cls.__new__(cls)
            print("obj ", obj, *args, **kwargs)
            print(cls)
            cls.__init__(obj, *args, **kwargs)
            return obj
    
        def __new__(mcs, *args, **kwargs):
            print("Mytype __new__", *args, **kwargs)
            return type.__new__(mcs, *args, **kwargs)
    
    
    print('here...')
    
    
    class Foo(object, metaclass=MyType):
        def __init__(self, name):
            self.name = name
    
            print("Foo __init__")
    
        def __new__(cls, *args, **kwargs):
            print("Foo __new__", cls, *args, **kwargs)
            return object.__new__(cls)
    
    
    f = Foo("Name")
    print("f", f)
    print("fname", f.name)

    类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

  • 相关阅读:
    IPC——信号量
    IPC——命名管道
    IPC——匿名管道
    IPC——信号
    管道和命名管道
    Oracle业务用户密码过期问题的解决
    Oracle获取数据库中的对象创建语句
    RAC禁用DRM特性
    配置Server Side TAF
    同一环境下新建Standby RAC库
  • 原文地址:https://www.cnblogs.com/dbf-/p/10649162.html
Copyright © 2020-2023  润新知