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__

原文地址:https://www.cnblogs.com/dbf-/p/10649162.html