Does object-oriented science fail to understand? A detailed summary of object-oriented knowledge points

Preface

The text and pictures in this article are from the Internet and are for learning and communication purposes only, and do not have any commercial use. If you have any questions, please contact us for processing.

PS: If you need Python learning materials, you can click on the link below to get it by yourself

Python free learning materials, codes and exchange answers click to join


One, class and object

1.1, the structure of the class

class Human:
    """
    此类主要是构建人类
    """
    mind = '有思想'  # 第一部分:静态属性 属性 静态变量 静态字段
    dic = {}
    l1 = []

    def work(self):  # 第二部分:方法 函数 动态属性
        print('人类会工作')

1.2. Study the class from the perspective of class name

1.2.1, class name operation static properties

1) View all the contents of the class: the class name __dict __ method

class Human:
    """
    此类主要是构建人类
    """
    mind = '有思想'
    dic = {}
    l1 = []

    def work(self):
        # print(self)
        print('人类会工作')


print(Human.__dict__)   
# {'__module__': '__main__', '__doc__': '\n    此类主要是构建人类\n    ', 'mind': '有思想', 'dic': {}, 'l1': [], 'work': <function Human.work at 0x0000017D90897438>, '__dict__': <attribute '__dict__' of 'Human' objects>, '__weakref__': <attribute '__weakref__' of 'Human' objects>}

print(Human.__dict__['mind'])   # 有思想
# Human.__dict__['mind'] = '无脑'   # TypeError: 'mappingproxy' object does not support item assignment
# 通过这种方式只能查询,不能增删改.

2) Pass the almighty point.

# 通过万能的点 可以增删改查类中的单个属性
class Human:
    """
    此类主要是构建人类
    """
    mind = '有思想'
    dic = {}
    l1 = []

    def work(self):
        # print(self)
        print('人类会工作')


print(Human.mind)  # 查
Human.mind = '无脑'  # 改
print(Human.mind)
del Human.mind  # 删
Human.walk = '直立行走'
print(Human.walk)

Summary: If you want to query all the content in the class, use the first __dict__ method. If you only manipulate a single attribute, use the universal point method.

1.2.2, class name operation dynamic method

Prerequisite: Except for two special methods: static methods and class methods, methods in a class are generally not manipulated by class names

class Human:
    mind = '有思想'
    dic = {}
    l1 = []

    def work(self):
        print(self)
        print('人类会工作')

    def tools(self):
        print('人类会使用工具')


Human.work(111)
Human.tools(111)
# 下面可以做,但不用
Human.__dict__['work'](111)

1.3. Research the class from the perspective of the object

1.3.1 What is an object

The object comes out of the class, as long as the class name plus (), this is an instantiation process, this will instantiate an object

class Human:
    mind = '有思想'

    def __init__(self):
        print(666)
        print(self)  # <__main__.Human object at 0x00000191508AA828>

    def work(self):
        print('人类会工作')

    def tools(self):
        print('人类会使用工具')


obj = Human()  # 只要实例化对象,它会自动执行__init__方法
print(obj)  # <__main__.Human object at 0x00000191508AA828>
# 并且obj的地址与self的地址相同

Three things about object instantiation:

  • 1) Open up an object space in memory
  • 2) The init method in the class is automatically executed , and the object space (memory address) is passed to the first positional parameter self of the init method
  • 3) Add attributes to the object space through self in the init method
class Human:
    mind = '有思想'
    language = '使用语言'

    def __init__(self, name, sex, age, hobby):
        # self 和 obj 指向的是同一个内存地址同一个空间,下面就是通过self给这个对象空间封装四个属性。
        self.n = name
        self.s = sex
        self.a = age
        self.h = hobby


obj = Human('barry', '男', 18, '运动')

1.3.2, object operation object space attributes

1) Object query all attributes in the object: object.__dict__

class Human:
    mind = '有思想'
    language = '实用语言'

    def __init__(self, name, sex, age, hobby):
        # self 和 obj 指向的是同一个内存地址同一个空间,下面就是通过self给这个对象空间封装四个属性。
        self.n = name
        self.s = sex
        self.a = age
        self.h = hobby


obj = Human('barry', '男', 18, '运动')
print(obj.__dict__)  # {'n': 'barry', 'h': '运动', 's': '男', 'a': 18}

2) The single attribute in the object operation object: the universal point.

class Human:
    mind = '有思想'
    language = '实用语言'

    def __init__(self, name, sex, age, hobby):
        # self 和 obj 指向的是同一个内存地址同一个空间,下面就是通过self给这个对象空间封装四个属性。
        self.n = name
        self.s = sex
        self.a = age
        self.h = hobby


obj = Human('barry', '男', 18, '运动')
obj.job = 'IT'  # 增
del obj.n  # 删
obj.s = '女'  # 改
print(obj.s)  # 查
print(obj.__dict__)  # {'s': '女', 'a': 18, 'h': '运动', 'job': 'IT'}

1.3.3, object view attributes in the class

class Human:
    mind = '有思想'
    language = '实用语言'

    def __init__(self, name, sex, age, hobby):
        self.n = name
        self.s = sex
        self.a = age
        self.h = hobby


obj = Human('barry', '男', 18, '运动')
print(obj.mind)  # 有思想
print(obj.language)  # 实用语言
obj.a = 666
print(obj.a)  # 666

1.3.4, the method in the object operation class

class Human:
    mind = '有思想'
    language = '实用语言'

    def __init__(self, name, sex, age, hobby):
        self.n = name
        self.s = sex
        self.a = age
        self.h = hobby

    def work(self):
        print(self)
        print('人类会工作')

    def tools(self):
        print('人类会使用工具')


obj = Human('barry', '男', 18, '运动')
obj.work()
obj.tools()

The methods in the class are generally executed through the object (except for the class method, static method), and the object executes these methods will automatically pass the object space to the first parameter self in the method

Self definition: self is actually the first positional parameter of the method (function) in the class, but the interpreter will automatically pass the object calling this function to self. So we set the first parameter of the method in the class to self by convention, which means this is the object

1.4, the class space problem

1.4.1, where can add object properties

class A:
    def __init__(self, name):
        self.name = name

    def func(self, sex):
        self.sex = sex


# 类外面可以:
obj = A('barry')
obj.age = 18
print(obj.__dict__)  # {'name': 'barry', 'age': 18}

# 类内部也可以:
obj = A('barry')  # __init__方法可以。
obj.func('男')  # func 方法也可以。

Summary: The attributes of an object can be added not only in __init__, but also in other methods of the class or outside the class

1.4.2, where can add static properties of the class

class A:
    def __init__(self, name):
        self.name = name

    def func(self, sex):
        self.sex = sex

    def func1(self):
        A.bbb = 'ccc'


# 类的外部可以添加
A.aaa = 'taibai'
print(A.__dict__['aaa'])    # taibai

# 类的内部也可以添加。
A.func1(111)
print(A.__dict__['bbb'])    # ccc

Summary: The attributes of a class can be added not only inside the class, but also outside the class

1.4.3, how the object finds the attributes of the class

 


The order of object search attributes: first find from the object space------> find from the class space------> find from the parent space------->.....

 

The order of class name search attributes: first find from this class space -------> parent class space -------> ........

1.5, the relationship between class and class

1.5.1, dependencies

Dependency: Pass the class name or object of one class to the method of another class

class Elephant:
    def __init__(self, name):
        self.name = name

    def open(self, ref):
        # print(ref)
        print(f'{self.name}默念三声: 芝麻开门,{ref.name}冰箱门打开')
        ref.open_door()     # 调用其他对象的方法

    def close(self):
        print('大象默念三声:芝麻关门')


class Refrigerator:
    def __init__(self, name):
        self.name = name

    def open_door(self):
        print(f'{self.name}冰箱门被打开了....')

    def close_door(self):
        print(f'{self.name}冰箱门被关上了....')


ele = Elephant('琪琪')
ref = Refrigerator('美菱')
ele.open(ref)

1.5.2, Combination relationship

Combination:  encapsulate objects of one class into properties of objects of another class

class Boy:

    def __init__(self, name):
        self.name = name

    def meet(self, girl_friend=None):
        self.girl_friend = girl_friend

    def have_diner(self):
        if self.girl_friend:
            print(f'{self.name}请年龄为:{self.girl_friend.age},姓名为{self.girl_friend.name}一起吃六块钱的麻辣烫')
            self.girl_friend.shopping(self)
        else:
            print('单身狗,吃什么吃')


class Girl:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def shopping(self, boy_friend):
        print(f'{boy_friend.name},{self.name}一起去购物!')

wu = Boy('吴超')
flower = Girl('如花', 48)
wu.meet(flower)
wu.have_diner()
"""
吴超请年龄为:48,姓名为如花一起吃六块钱的麻辣烫
吴超,如花一起去购物!
"""

Requirement: Write a game character class to simulate League of Legends

1. Create a Game_role class.
2. In the construction method, encapsulate name, ad (attack power), hp (hp). Three attributes for the object.
1. Create an attack method, this method is to instantiate two objects, The function of mutual attack: Example: instantiate an object Galen, ad is 10, hp is 100 instantiate another object Jianhao ad is 20, hp is 80 Galen uses the attack method to attack Jianhao, the method must be completed'Who The attacker, who lost how much blood, and how much blood is left' prompt function.

class GameRole:

    def __init__(self, name, ad, hp):
        self.name = name
        self.ad = ad
        self.hp = hp

    def attack(self, p1):
        p1.hp = p1.hp - self.ad
        print(f'{self.name}攻击{p1.name},{p1.name}掉了{self.ad}血,还剩{p1.hp}血')

    def equit_weapon(self, weapon):
        self.weapon = weapon  # 组合: 给对象封装了一个为weapon属性


class Weapon:

    def __init__(self, name, ad):
        self.name = name
        self.ad = ad

    def weapon_attack(self, p1, p2):
        p2.hp = p2.hp - self.ad
        print(f'{p1.name}利用{self.name}给了{p2.name}一下,{p2.name}还剩{p2.hp}血')

gailun = GameRole('盖伦', 10, 100)
zhaoxin = GameRole('赵信', 20, 90)
great_sword = Weapon('宝剑', 30)
gailun.equit_weapon(great_sword)  # 依赖关系
gailun.weapon.weapon_attack(gailun, zhaoxin)

1.6, class constraints

1) Method one
extracts the class, and then defines the method in the class. Nothing is used in this method. Just throw an exception. So all subclasses must rewrite this method . Otherwise, an error will be reported during the visit.

class Payment:
    """
    此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
    """

    def pay(self, money):
        raise Exception("你没有实现pay方法")


class QQpay(Payment):
    def pay(self, money):
        print('使用qq支付%s元' % money)


class Alipay(Payment):
    def pay(self, money):
        print('使用阿里支付%s元' % money)


class Wechatpay(Payment):
    # 未实现pay方法报错
    # def fuqian(self, money):
    #     print('使用微信支付%s元' % money)

    def pay(self, money):
        print(f'使用微信支付{money}元')


def pay(obj, money):
    obj.pay(money)


a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a, 100)
pay(b, 200)
pay(c, 300)

2) Method 2
Use metaclasses to describe classes. An abstract method is given in the metaclass. In this way, the subclass has to give concrete implementations of the abstract method

from abc import ABCMeta, abstractmethod


class Payment(metaclass=ABCMeta):  # 抽象类 接口类  规范和约束  metaclass指定的是一个元类
    @abstractmethod
    def pay(self, money):  # 抽象方法
        pass


class Alipay(Payment):
    def pay(self, money):
        print('使用支付宝支付了%s元' % money)


class QQpay(Payment):
    def pay(self, money):
        print('使用qq支付了%s元' % money)


class Wechatpay(Payment):
    def pay(self,money):
        print('使用微信支付了%s元'%money)
    # def recharge(self): pass    # TypeError: Can't instantiate abstract class Wechatpay with abstract methods pay


def pay(a, money):
    a.pay(money)


a = Alipay()
pay(a, 100)  # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能

q = QQpay()
pay(q, 100)

w = Wechatpay()
pay(w, 100)  # 到用的时候才会报错

Two, object-oriented: inheritance

2.1, what is inheritance

# 继承的用法:
class Aniaml(object):
    def __init__(self, name, sex, age):
        self.name = name
        self.age = age
        self.sex = sex


class Person(Aniaml):
    pass

class Cat(Aniaml):
    pass

class Dog(Aniaml):
    pass

Inherited advantages:

  • 1) Increase the coupling of the class (the coupling should not be too much, it should be refined)
  • 2) Reduced repetitive code
  • 3) Make the code more standardized and rational

2.2, single inheritance

2.2.1, the class name, the object executes the parent class method

class Aniaml(object):
    type_name = '动物类'

    def __init__(self, name, sex, age):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        print(self)
        print('吃东西')


class Person(Aniaml):
    pass


class Cat(Aniaml):
    pass


class Dog(Aniaml):
    pass


# 类名:
print(Person.type_name)  # 可以调用父类的属性,方法。
Person.eat(111)

# 对象:
p1 = Person('春哥', '男', 18)
print(p1.__dict__)  # {'name': '春哥', 'age': 18, 'sex': '男'}
# 对象执行类的父类的属性,方法。
print(p1.type_name)
p1.type_name = '666'
print(p1.__dict__)  # {'name': '春哥', 'age': 18, 'sex': '男', 'type_name': '666'}
p1.eat()

2.2.2, execution sequence

class Aniaml(object):
    type_name = '动物类'

    def __init__(self, name, sex, age):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        # print(self)
        print('吃东西')


class Person(Aniaml):
    def eat(self):
        # print('%s 吃饭' % self.name)
        print(f'{self.name} 吃饭')


class Cat(Aniaml):
    pass


class Dog(Aniaml):
    pass


p1 = Person('barry', '男', 18)
# 实例化对象时必须执行__init__方法,类中没有,从父类找,父类没有,从object类中找。
p1.eat()
# 先要执行自己类中的eat方法,自己类没有才能执行父类中的方法。

2.2.3, simultaneous execution of the class and the parent class method

1) Method 1: Parent class. func (object, other parameters)

class Aniaml(object):
    type_name = '动物类'

    def __init__(self, name, sex, age):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        print('吃东西')


class Person(Aniaml):
    def __init__(self, name, sex, age, mind):
        Aniaml.__init__(self, name, sex, age)  # 方法一
        self.mind = mind

    def eat(self):
        super().eat()
        print('%s 吃饭' % self.name)


class Cat(Aniaml):
    pass


class Dog(Aniaml):
    pass


# 方法一:Aniaml.__init__(self,name,sex,age)
p1 = Person('春哥', 'laddboy', 18, '有思想')  
print(p1.__dict__)      # {'name': '春哥', 'age': 18, 'sex': 'laddboy', 'mind': '有思想'}
p1.eat()

2) Method 2: super().func(parameter)

class Aniaml(object):
    type_name = '动物类'

    def __init__(self, name, sex, age):
        self.name = name
        self.age = age
        self.sex = sex

    def eat(self):
        print('吃东西')


class Person(Aniaml):
    def __init__(self, name, sex, age, mind):
        # super(Person,self).__init__(name,sex,age)  # 方法二
        super().__init__(name, sex, age)  # 方法二
        self.mind = mind

    def eat(self):
        super().eat()
        print('%s 吃饭' % self.name)


class Cat(Aniaml):
    pass


class Dog(Aniaml):
    pass


p1 = Person('春哥', 'laddboy', 18, '有思想')
print(p1.__dict__)  # {'name': '春哥', 'age': 18, 'sex': 'laddboy', 'mind': '有思想'}

2.2.4, single inheritance exercise

class Base:

    def __init__(self, num):
        self.num = num

    def func1(self):
        print(self.num)


class Foo(Base):
    pass


obj = Foo(123)
obj.func1()  # 123

# -------------------------------------------------
class Base:
    def __init__(self, num):
        self.num = num

    def func1(self):
        print(self.num)


class Foo(Base):

    def func1(self):
        print("Foo. func1", self.num)


obj = Foo(123)
obj.func1()  # Foo. func1 123

# -------------------------------------------------
class Base:
    def __init__(self, num):  # 2
        self.num = num

    def func1(self):  # 4
        print(self.num)  # 123
        self.func2()  # self ---> obj  # 对象查询顺序:

    def func2(self):
        print("Base.func2")


class Foo(Base):
    def func2(self):
        print("Foo.func2")


obj = Foo(123)  # 1
obj.func1()  # 3
'''
123
Foo.func2
'''

# -------------------------------------------------
class Base:
    def __init__(self, num):
        self.num = num

    def func1(self):
        print(self.num)
        self.func2()

    def func2(self):
        print(111, self.num)


class Foo(Base):

    def func2(self):
        print(222, self.num)


lst = [Base(1), Base(2), Foo(3)]

for obj in lst:
    obj.func2()
'''
111 1
111 2
222 3
'''

# -------------------------------------------------
class Base:

    def __init__(self, num):
        self.num = num

    def func1(self):
        print(self.num)
        self.func2()

    def func2(self):
        print(111, self.num)


class Foo(Base):

    def func2(self):
        print(222, self.num)


lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
    obj.func1()
'''
1
111 1
2
111 2
3
222 3
'''

2.2.5, super in-depth understanding

Super is strictly executed in accordance with the inheritance order of the class (mro algorithm)
1) Example 1

class A:
    def f1(self):
        print('in A f1')

    def f2(self):
        print('in A f2')


class Foo(A):
    def f1(self):
        super().f2()
        print('in A Foo')


obj = Foo()
obj.f1()
"""
in A f2
in A Foo
"""

2) Example two

class A:
    def f1(self):
        print('in A')


class Foo(A):
    def f1(self):
        super().f1()
        print('in Foo')


class Bar(A):
    def f1(self):
        print('in Bar')


class Info(Foo, Bar):
    def f1(self):
        super().f1()
        print('in Info f1')


obj = Info()
obj.f1()

'''
in Bar
in Foo
in Info f1
'''
print(
    Info.mro())  # [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>]

3) Example three

class A:
    def f1(self):
        print('in A')


class Foo(A):
    def f1(self):
        super().f1()
        print('in Foo')


class Bar(A):
    def f1(self):
        print('in Bar')


class Info(Foo, Bar):
    def f1(self):
        super(Foo, self).f1()   # 多继承: super(S,self) 严格按照self从属于的类的mro的执行顺序,执行 S类的下一位
        print('in Info f1')

print(Info.mro())   # [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>]
print(Foo.mro())    # [<class '__main__.Foo'>, <class '__main__.A'>, <class 'object'>]
obj = Info()
obj.f1()

super() summary:
super() is not strictly a method of executing the parent class. Single inheritance: super() is definitely a method of executing the parent class. Multiple inheritance: super(S,self) strictly in accordance with the mro of the class to which self belongs The execution order of S is the next bit of class S.

2.3, multiple inheritance

class God:

    def fly(self):
        print('会飞')

    def climb(self):
        print('神仙累了也需要爬树')


class Monkey:

    def climb(self):
        print('爬树')


class MonkeySun(God, Monkey):
    pass


# 多继承的难点就是继承顺序的问题
sun = MonkeySun()
sun.climb()  # 神仙累了也需要爬树
print(MonkeySun.mro())  
# 继承顺序是根据类的mro()算法计算的
# [<class '__main__.MonkeySun'>, <class '__main__.God'>, <class '__main__.Monkey'>, <class 'object'>]

2.4. Keywords: isinstance and issubclass

# isinstance 判断的是对象与类的关系
class A:
    pass


class B(A):
    pass


obj = B()

# isinstance(a,b) 判断的是 a是否是b类 或者 b类派生类 实例化的对象.
print(isinstance(obj, B))  # True
print(isinstance(obj, A))  # True


# ----------------------------------------
# issubclass 类与类之间的关系

class A:
    pass


class B(A):
    pass


class C(B):
    pass


# issubclass(a,b) 判断的是 a类是否是b类 或者 b类派生类 的派生类.
# issubclass(a,b) 判断的是 a类是否是b类 子孙类.
print(issubclass(B, A))  # True
print(issubclass(C, A))  # True

2.5, metaclass

The type metaclass is also called the construction class. Most of the built-in classes in python (including object) and self-defined classes are created by the type metaclass

The relationship between type and object is unique: object is an instance of type, and type is a subclass of object

obj = A()
print(type('abc'))      # <class 'str'>
print(type([1, 2, 3]))  # <class 'list'>
print(type((22, 33)))   # <class 'tuple'>

# type 获取对象从属于的类
print(type(A))  # <class 'type'>
print(type(str))    # <class 'type'>
print(type(dict))   # <class 'type'>

# python 中一切皆对象, 类在某种意义上也是一个对象,python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的.

# type 与 object 的关系.
print(type(object))  # <class 'type'> object类是type类的一个实例.
# object类是type类的父类.
print(issubclass(type, object))  # True

Three, object-oriented: encapsulation

3.1, what is encapsulation

Encapsulation: Encapsulate a lot of data into an object. Encapsulate fixed-function code into a code block, function, object, and package it into a module. This is the idea of ​​encapsulation

3.2, package content call

1) Directly call the encapsulated content through the object

class Foo:

    def __init__(self, name, age):
        self.name = name
        self.age = age


obj1 = Foo('wupeiqi', 18)
print(obj1.name)  # 直接调用obj1对象的name属性
print(obj1.age)  # 直接调用obj1对象的age属性

obj2 = Foo('alex', 73)
print(obj2.name)  # 直接调用obj2对象的name属性
print(obj2.age)  # 直接调用obj2对象的age属性

2) Indirectly call the encapsulated content through self

class Foo:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def detail(self):
        print(self.name)
        print(self.age)


obj1 = Foo('wupeiqi', 18)
obj1.detail()

obj2 = Foo('alex', 73)
obj2.detail()

In summary, for object-oriented encapsulation, it is actually to use the construction method to encapsulate the content into the object, and then obtain the encapsulated content directly or indirectly through the object.

Fourth, object-oriented: polymorphism

4.1, what is polymorphism

Polymorphism refers to a type of things with multiple forms. Polymorphism points out how to operate and access through their common attributes and actions, without considering their collective type.

# 多态
import abc


class Animal(metaclass=abc.ABCMeta):  # 同一类事物:动物
    @abc.abstractmethod
    def talk(self):
        pass


class People(Animal):  # 动物的形态之一:人
    def talk(self):
        print('say hello')


class Dog(Animal):  # 动物的形态之二:狗
    def talk(self):
        print('say wangwang')


class Pig(Animal):  # 动物的形态之三:猪
    def talk(self):
        print('say aoao')


# -------------------------------------------
class H2O:
    def __init__(self, name, temperature):
        self.name = name
        self.temperature = temperature

    def turn_ice(self):
        if self.temperature < 0:
            print('[%s]温度太低结冰了' % self.name)
        elif self.temperature > 0 and self.temperature < 100:
            print('[%s]液化成水' % self.name)
        elif self.temperature > 100:
            print('[%s]温度太高变成了水蒸气' % self.name)


class Water(H2O):
    pass


class Ice(H2O):
    pass


class Steam(H2O):
    pass


w1 = Water('水', 25)
i1 = Ice('冰', -20)
s1 = Steam('蒸汽', 3000)

4.2, duck model

class A:

    def login(self):
        pass

    def register(self):
        pass


class B:

    def login(self):
        pass

    def register(self):
        pass

# A,B两个类,没有任何关系,独立两个,但是里面的功能相似,所以python一般会将类似于A,B两个类里面的相似的功能让其命名相同.
# A,B虽然无关系,但是很默契的制定了一个规范.让你使用起来更方便.
# str  tuple list 都有 index方法,这就是统一了规范

Five, the members of the class

5.1. Subdivided members

class A:
    company_name = '点筹'  # 静态变量(静态字段)
    __iphone = '1353333xxxx'  # 私有静态变量(私有静态字段)

    def __init__(self, name, age):  # 特殊方法
        self.name = name  # 对象属性(普通字段)
        self.__age = age  # 私有对象属性(私有普通字段)

    def func1(self):  # 普通方法
        pass

    def __func(self):  # 私有方法
        print(666)

    @classmethod  # 类方法
    def class_func(cls):
        """ 定义类方法,至少有一个cls参数 """
        print('类方法')

    @staticmethod  # 静态方法
    def static_func():
        """ 定义静态方法 ,无默认参数"""
        print('静态方法')

    @property  # 属性
    def prop(self):
        pass

5.2, private members of the class

5.2.1, static fields

Static field (static attribute):

  • Public static field: the class can be accessed; the class can be accessed; the derived class can be accessed
  • Private static field: only accessible inside the class

1) Public static fields

class C:
    name = "公有静态字段"

    def func(self):
        print(C.name)


class D(C):

    def show(self):
        print(C.name)


# 类访问
print(C.name)
# 类内部可以访问
obj = C()
obj.func()
# 派生类中可以访问
obj_son = D()
obj_son.show()

2) Private static fields

class C:
    __name = "私有静态字段"

    def func(self):
        print(C.__name)


class D(C):

    def show(self):
        print(C.__name)


# print(C.__name)  # 不可在外部访问

obj = C()
# print(obj.__name)  # 不可在外部访问
obj.func()  # 类内部可以访问

# obj_son = D()
# obj_son.show()  # 不可在派生类中可以访问

5.2.2, common fields (object attributes)

Ordinary field (object attribute)

  • Public common fields: objects can be accessed; within the class can be accessed; can be accessed in derived classes
  • Private common fields: only accessible within the class;

1) Public common field

class C:
    def __init__(self):
        self.foo = "公有字段"

    def func(self):
        print(self.foo)  # 类内部访问


class D(C):
    def show(self):
        print(self.foo)  # 派生类中访问


obj = C()
print(obj.foo)  # 通过对象可以访问
obj.func()  # 类内部可以访问

obj_son = D()
obj_son.show()  # 派生类中访问

2) Private common field

class C:
    def __init__(self):
        self.__foo = "私有字段"
        
    def func(self):
        print(self.__foo)  # 类内部访问


class D(C):
    def show(self):
        print(self.__foo)  # 派生类中访问


obj = C()

# print(obj.__foo)  # 通过对象访问    ==> 错误
obj.func()  # 类内部访问        ==> 正确

# obj_son = D()
# obj_son.show()  # 派生类中访问  ==> 错误

5.2.3, method

method:

  • Public methods: objects can be accessed; classes can be accessed; they can be accessed in derived classes
  • Private method: only accessible inside the class;

1) Public methods

class C:
    def __init__(self):
        pass

    def add(self):
        print('in C')


class D(C):
    def show(self):
        print('in D')

    def func(self):
        self.show()


obj = D()
obj.show()  # 通过对象访问
obj.func()  # 类内部访问
obj.add()  # 派生类中访问

2) Private method

class C:
    def __init__(self):
        pass

    def __add(self):
        print('in C')


class D(C):
    def __show(self):
        print('in D')

    def func(self):
        self.__show()


obj = D()
# obj.__show()  # 通过不能对象访问
obj.func()  # 类内部可以访问
# obj.__add()  # 派生类中不能访问

to sum up:

For these private members, they can only be used inside the class, and cannot be used outside the class or in derived classes.

PS: If you have to access private members, you can pass the object._ class__ attribute name, but it is absolutely not allowed

Because when the class is created, if it encounters private members (including private static fields, private ordinary fields, private methods), it will automatically add _ class name in front of it when it is stored in memory.

5.3, other members of the class

1) Instance method
Definition: The first parameter must be an instance object, the parameter name is generally agreed to be self, through which the properties and methods of the instance are passed (the properties and methods of the class can also be passed);

Call: It can only be called by an instance object.
2) Class method
Definition: Use the decorator @classmethod. The first parameter is the current class object, the parameter name is generally agreed to be cls, through which the properties and methods of the class are passed (the properties and methods of the instance cannot be passed);

Call: Both instance objects and class objects can be called.

class Student:
    __num = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        Student.addNum()  # 写在__new__方法中比较合适,暂且放到这里

    @classmethod
    def addNum(cls):
        cls.__num += 1

    @classmethod
    def getNum(cls):
        return cls.__num


a = Student('A', 18)
b = Student('B', 36)
c = Student('C', 73)
print(Student.getNum())

3) Static method
Definition: Use the decorator @staticmethod. The parameters are arbitrary, there are no self and cls parameters, but any attributes and methods of the class or instance cannot be used in the method body;

Call: Both instance objects and class objects can be called.

Static methods are mainly used to store logical code, logically belong to the class, but have nothing to do with the class itself, that is to say, in the static method, the operation of the attributes and methods in the class will not be involved. It can be understood that the static method is an independent and pure function, which is only hosted in the namespace of a certain class, which is easy to use and maintain

import time


class TimeTest(object):
    def __init__(self, hour, minute, second):
        self.hour = hour
        self.minute = minute
        self.second = second

    @staticmethod
    def showTime():
        return time.strftime("%H:%M:%S", time.localtime())


print(TimeTest.showTime())  # 类直接调用
t = TimeTest(2, 10, 10)
nowTime = t.showTime()      # 对象调用
print(nowTime)

4) The
definition of the double-click method (to be discussed later) : the double-click method is a special method. It is a method provided by the interpreter with a special meaning of double underscore plus method name plus double underscore. The double-click method is mainly used by Python source code programmers. in use,

We try not to use the double download method in the development, but in-depth study of the double download method is more beneficial for us to read the source code

5.4, ​​attributes

Property is a special property, when you access it, a function (function) will be executed and then the value will be returned

class People:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)


p1 = People('egon', 75, 1.85)
print(p1.bmi)

Since there are three access methods in the new-style class, we can define the three methods respectively to the same attribute according to the access characteristics of their several attributes: get, modify, delete

class Foo:
    @property
    def AAA(self):
        print('get的时候运行我啊')

    @AAA.setter
    def AAA(self, value):
        print('set的时候运行我啊')

    @AAA.deleter
    def AAA(self):
        print('delete的时候运行我啊')


# 只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1 = Foo()
f1.AAA
f1.AAA = 'aaa'
del f1.AAA
"""
get的时候运行我啊
set的时候运行我啊
delete的时候运行我啊
"""

# -------------------------------------------------------
# 或者:
class Foo:
    def get_AAA(self):
        print('get的时候运行我啊')

    def set_AAA(self, value):
        print('set的时候运行我啊')

    def delete_AAA(self):
        print('delete的时候运行我啊')

    AAA = property(get_AAA, set_AAA, delete_AAA)  # 内置property三个参数与get,set,delete一一对应


f1 = Foo()
f1.AAA
f1.AAA = 'aaa'
del f1.AAA

Commodity examples:

class Goods(object):

    def __init__(self):
        # 原价
        self.original_price = 100
        # 折扣
        self.discount = 0.8

    @property
    def price(self):
        # 实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price

    @price.setter
    def price(self, value):
        self.original_price = value

    @price.deleter
    def price(self):
        del self.original_price

obj = Goods()
print(obj.price)         # 获取商品价格
obj.price = 200   # 修改商品原价
print(obj.price)
del obj.price     # 删除商品原价

5.5, function vs method

1) Determine by printing the function (method) name

def func():
    pass


print(func)  # <function func at 0x00000260A2E690D0>


class A:
    def func(self):
        pass


print(A.func)  # <function A.func at 0x0000026E65AE9C80>
obj = A()
print(obj.func)  # <bound method A.func of <__main__.A object at 0x00000230BAD4C9E8>>

2) Verify through the types module

from types import FunctionType
from types import MethodType


def func():
    pass


class A:
    def func(self):
        pass


obj = A()

print(isinstance(func, FunctionType))  # True
print(isinstance(A.func, FunctionType))  # True
print(isinstance(obj.func, FunctionType))  # False
print(isinstance(obj.func, MethodType))  # True

3) Static methods are functions

from types import FunctionType
from types import MethodType


class A:

    def func(self):
        pass

    @classmethod
    def func1(self):
        pass

    @staticmethod
    def func2(self):
        pass


obj = A()

# 类方法
print(isinstance(A.func1, MethodType))  # True
print(isinstance(obj.func1, MethodType))  # True
# 静态方法其实是函数
print(isinstance(A.func2, FunctionType))  # True
print(isinstance(obj.func2, FunctionType))  # True

Summary: Functions are all explicit pass parameters, and methods are all implicit pass parameters

Six, reflection

Reflection in Python object-oriented: Manipulate object-related attributes in the form of strings. Everything in python is an object (reflection can be used)

6.1, the reflection of the object

class Foo:
    f = '类的静态变量'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hi(self):
        print('hi,%s' % self.name)


obj = Foo('egon', 73)

# 检测是否含有某属性
print(hasattr(obj, 'name'))     # True
print(hasattr(obj, 'say_hi'))   # True

# 获取属性
n = getattr(obj, 'name')
print(n)    # egon
func = getattr(obj, 'say_hi')
func()      # hi,egon

print(getattr(obj, 'aaaaaaaa', '不存在啊'))  # 默认设置

# 设置属性
setattr(obj, 'sb', True)
setattr(obj, 'show_name', lambda self: self.name + 'abc')
print(obj.__dict__)     # {'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x000002E2F1EDE828>}
print(obj.show_name(obj))   # egonabc

# 删除属性
delattr(obj, 'age')
delattr(obj, 'show_name')
# delattr(obj, 'show_name111')  # 不存在,则报错
print(obj.__dict__) # {'name': 'egon', 'sb': True}

6.2, class reflection

class Foo(object):
    staticField = "酸菜鱼"

    def __init__(self):
        self.name = 'wupeiqi'

    def func(self):
        return 'func'

    @staticmethod
    def bar():
        return 'bar'

f = Foo()
print(getattr(Foo, 'staticField'))
print(getattr(Foo, 'func')(f))
print(getattr(Foo, 'bar')())

6.3, the reflection of the current module

import sys


def s1():
    print('s1')


def s2():
    print('s2')


this_module = sys.modules[__name__]
print(this_module)

print(hasattr(this_module, 's1'))   # True
getattr(this_module, 's2')()    # s2

6.4 Reflection of other modules

Other modules:

# 文件名:tbjx.py

name = '酸菜鱼'

def func():
    print('in tbjx func')



class C:
    area = '北京'

    def __init__(self,name):
        self.name = name

    def func(self):
        print('in B func')

Reflection of other modules:

import tbjx

print(getattr(tbjx, 'name'))
getattr(tbjx, 'func')()

# 1. 找到tbjx对象 的C类,实例化一个对象.
print(getattr(tbjx, 'C'))
obj = getattr(tbjx, 'C')('123')
print(obj)

# 2. 找到tbjx对象 的C类,通过对C类这个对象使用反射取到area.
print(getattr(tbjx.C, 'area'))

# 3. 找到tbjx对象 的C类,实例化一个对象,对对象进行反射取值.
obj = getattr(tbjx, 'C')('abc')
print(obj.name)
print(getattr(obj, 'name'))

6.5 Application of reflection

class User:
    def login(self):
        print('欢迎来到登录页面')

    def register(self):
        print('欢迎来到注册页面')

    def save(self):
        print('欢迎来到存储页面')


user = User()
while 1:
    choose = input('>>>').strip()
    if hasattr(user, choose):
        func = getattr(user, choose)
        func()
    else:
        print('输入错误。。。。')

Seven, double underline method

7.1, __len__ method

# len 一个对象就会触发 __len__方法
class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)
a = A()
print(len(a)) # 2

7.2, __hash__ method

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __hash__(self):
        return hash(str(self.a)+str(self.b))
a = A()
print(hash(a))

7.3, __str__ method

If the __str__ method is defined in a class, the return value of the method will be output by default when printing the object, similar to the toString() method of java

class A:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __str__(self):
        return f'A [name = {self.name}, age = {self.age}]'


a = A('酸菜鱼', 18)
print(a)    # A [name = 运维人在路上, age = 18]

7.4, __repr__ method

# repr
# print('我叫%s' % ('运维人在路上'))  # 我叫运维人在路上
# print('我叫%r' % ('运维人在路上'))  # 我叫'运维人在路上'
# print(repr('fdsaf'))    # 'fdsaf'

class A:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        print(666)
        return f'姓名: {self.name} 年龄: {self.age}'


a = A('AA', 35)
b = A('BB', 56)
c = A('CC', 18)
# print(a)
print(repr(a))

7.5, __ call__ method

Add parentheses after the object to trigger execution.

Note: The execution of the constructor __new__ is triggered by the creation of an object, that is: object = class name (); and the execution of the __ call__ method is triggered by adding parentheses after the object, namely: object () or class ()()

class Foo:

    def __init__(self):
        print('__init__')
        pass

    def __call__(self, *args, **kwargs):
        print('__call__')


obj = Foo()  # 执行 __init__
obj()  # 执行 __call__

7.6, __eq__ method

Compare whether two objects are equal, similar to the equals() method in java

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __eq__(self, obj):
        if self.a == obj.a and self.b == obj.b:
            return True


a = A()
b = A()
print(a == b)   # True

7.7, __ del__ method

The destruction method automatically triggers execution when the object is released in memory.

Note: This method generally does not need to be defined, because Python is a high-level language, programmers do not need to care about the allocation and release of memory when using it, because this work is performed by the Python interpreter, so the destructor call is Automatically triggered by the interpreter during garbage collection

7.8, __new__ method

The object is generated by the __new__ method of the object class. The object is created using **class name()**. The following things happen:

1. First trigger the __new__ method of the object, which opens up an object space in memory.
2. Execute the __init__ method to encapsulate the attributes of the object.

class A(object):

    def __init__(self):

        self.x = 1
        print('in init function')

    def __new__(cls, *args, **kwargs):
        print('in new function')
        return object.__new__(A)

# 对象是object类的__new__方法 产生的.
a = A()
'''
in new function
in init function
'''

Singleton mode:

class A:
    __instance = None

    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = object.__new__(cls)
        return cls.__instance


obj = A('AAA')
print(obj.name)  # AAA
obj1 = A('BBB')
print(obj1.name)  # BBB
print(obj.name)  # BBB

7.9, __item__ series

class Foo:
    def __init__(self, name):
        self.name = name

    def __getitem__(self, item):
        print(self.__dict__[item])

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        print('del obj[key]时,我执行')
        self.__dict__.pop(key)

    def __delattr__(self, item):
        print('del obj.key时,我执行')
        self.__dict__.pop(item)


f1 = Foo('AAA')
f1['age'] = 18
f1['height'] = 19
print(f1.__dict__)  # {'name': 'AAA', 'age': 18, 'height': 19}

del f1.height   # del obj.key时,我执行
del f1['age']   # del obj[key]时,我执行
f1['name'] = '酸菜鱼'
print(f1.__dict__)  # {'name': '酸菜鱼'}

Guess you like

Origin blog.csdn.net/pythonxuexi123/article/details/114749359