多态与反射

一、多态

1.什么是多态

多态指的是同一种类型的事物,不同的形态。

例如,猪,狗,猫都是动物,都有叫声这个技能,但是狗是“汪汪汪”,猪是“哼哼哼”,猫是“喵喵喵”。它们之间的叫声不同,也就有了不同的区分

 1 # 动物类
 2 class Animal:
 3 
 4     # 方法 叫
 5     def speak(self):
 6         pass
 7 # 猪类
 8 class Pig(Animal):
 9 
10     def speak(self):
11         print('哼哼哼...')
12 
13 
14 # 猫类
15 class Cat(Animal):
16 
17     def speak(self):
18         print('喵喵喵...')
19 
20 
21 # 狗类
22 class Dog(Animal):
23 
24     def speak(self):
25         print('汪汪汪...')
26 
27 
28 animal1 = Dog()
29 animal2 = Pig()
30 animal3 = Cat()
31 
32 # 让动物们叫起来
33 animal1.speak()
34 animal2.speak()
35 animal3.speak()

2.多态作用

  “多态” 也称之为 “多态性”,目的是为了 在不知道对象具体类型的情况下,统一对象调用方法的规范(比如:名字)。

多态的表现 “形式之一” 就是继承:
- 先抽象,再继承

父类: 定制一套统一的规范。(比如: 方法名统一)
子类: 遵循父类的统一的规范。(比如: 子类遵循父类方法名的统一)

二、抽象类

在python中不会强制限制子类必须要遵循父类的规范,所以出现了抽象类

1.什么是抽象类

在python内置的abc模块中,有一个抽象类

2.抽象类的作用

让子类必须遵循父类的编写规范

3.怎么实现抽象类

- 父类需要继承abc模块中,metaclass=abc.ABCMeta
- 在父类的方法中,需要装饰上 abc.abstractmethod

注意: 在python中不推荐使用抽象类。

注意: 子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)

 1 import abc
 2 
 3 class Animal(metaclass= abc.ABCMeta):
 4     @abc.abstractmethod
 5     def eat(self):
 6         pass
 7 
 8     @abc.abstractmethod
 9     def speak(self):
10         pass
11 
12 
13 class Dog(Animal):
14     def eat(self):
15         print('')
16 
17     def speak(self):
18         print('汪汪汪')
19 
20 
21 dog_obj = Dog()
22 dog_obj.speak()

三、鸭子类型

1.什么是鸭子类型

不同的对象,只要长得像鸭子,动作行为像鸭子,那它就是鸭子。鸭子类型是多态的一种表现形式。

2.鸭子类型作用

不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。所有的类,在定义时都按照统一的规范进行编写。降低程序的耦合度。提升了程序的可扩展性

 1 # 猪类
 2 class Pig:
 3     def eat(self):
 4         print('bia唧...')
 5 
 6     def speak(self):
 7         print('哼哼哼...')
 8 
 9 
10 # 猫类
11 class Cat:
12     def eat(self):
13         print('咬ji 咬ji....')
14 
15     def speak(self):
16         print('喵喵喵...')
17 
18 
19 # 狗类
20 class Dog:
21     def eat(self):
22         print('舔 ji 舔ji...')
23 
24     def speak(self):
25         print('汪汪汪...')
26 
27 
28 def animal_speak(animal):
29     animal.speak()
30 
31 
32 dog = Dog()
33 pig = Pig()
34 cat = Cat()
35 animal_speak(dog)
36 animal_speak(pig)
37 animal_speak(cat)
1 # 自定义统计长度
2 def my_len(obj):
3     return obj.__len__()
4 
5 str1 = '123456789'
6 list1 = [1, 2, 3, 4, 5]
7 print(my_len(str1))
8 print(my_len(list1))

小结:

- 多态的三种表现形式:
  - 继承父类 :
    - 耦合度高,程序的可扩展性低

  - 继承抽象类:
    - 耦合度极高,程序的可扩展性极低

  - 鸭子类型:
    - 耦合度低,程序的可扩展性高

注意: 在python中,强烈推荐使用鸭子类型。

四、classmethod 和 staticmethod

classmethod与staticmethod都是python解释器内置的装饰器

1.classmethod

是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “类的绑定方法”。

 1 # classmethod
 2 class DB:
 3     __data = 'abc'
 4     def __init__(self, user, pwd):
 5         self.user = user
 6         self.pwd = pwd
 7 
 8 
 9     @classmethod
10     def check(cls, user, pwd):
11         obj = cls(user, pwd)
12         if obj.user == 'aaa' and obj.pwd == '123':
13             print('验证通过...')
14             print(cls.__data)
15 
16 DB.check('aaa', '123')

2.staticmethod

是一个装饰器,给在类内部定义方法中装饰,将类内部的方法变为 “非绑定方法”。

 1 # staticmethod
 2 class Foo:
 3     @staticmethod
 4     def print_info(self):
 5         print(self)
 6 
 7 obj = Foo()
 8 
 9 # 对象调用非绑定方法
10 obj.print_info(123)
11 
12 # 类调用非绑定方法
13 Foo.print_info(1234)

小结

- 对象的绑定方法:
  - 由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入。

- 类的绑定方法:
  - 由类来调用,由谁来调用,会将谁(类)当做第一个参数传入。

- 非绑定方法:
  - 可以由对象或类来调用,谁来调用都是一个普通方法(普通函数),方法需要传入几个参数,就得传入几个。

五、isinstance 和 issubclass

1.isinstance

判断一个对象是否是另一个类的实例。
- 如果是: True,且这个对象也是该类的父类的一个实例
- 如果不是: False

 1 class Foo:
 2     pass
 3 
 4 class Sub(Foo):
 5     pass
 6 
 7 class Oth:
 8     pass
 9 
10 o_obj = Oth()
11 s_obj = Sub()
12 
13 # isinstance
14 print(isinstance(s_obj, Sub))   # True
15 print(isinstance(s_obj, Foo))   # True
16 print(isinstance(s_obj, Oth))   # False

2.issubclass

判断一个类是否是另一个类的子类。
- 如果是: True
- 如果不是: False

 1 class Foo:
 2     pass
 3 
 4 class Sub(Foo):
 5     pass
 6 
 7 class Oth:
 8     pass
 9 
10 o_obj = Oth()
11 s_obj = Sub()
12 
13 # issubclass
14 print(issubclass(Sub, Foo))     # True
15 print(issubclass(Sub, Oth))     # False

六、反射

反射指的是通过 “字符串” 对 对象的属性进行操作。

1.hasattr

通过 “字符串” 判断对象的属性或方法是否存在。

2.getattr

 通过 “字符串” 获取对象的属性或方法。

3.setattr

通过 “字符串” 设置对象的属性或方法。

4.delattr

通过 “字符串” 删除对象的属性或方法。

 1 class Foo:
 2     def __init__(self, x, y):
 3         self.x = x
 4         self.y = y
 5 
 6 obj = Foo(10, 20)
 7 print(obj.__dict__)
 8 
 9 # hasattr
10 print(hasattr(obj, 'x'))    # True
11 print(hasattr(obj, 'z'))    # Flase
12 
13 # getattr
14 print(getattr(obj, 'x'))    # 10
15 # 若属性不存在,则返回默认值
16 print(getattr(obj, 'z', '不存在返回值'))    # 不存在返回值
17 
18 # setattr
19 setattr(obj, 'x', 30)
20 print(obj.__dict__)     # {'x': 30, 'y': 20}
21 setattr(obj, 'z', '123')
22 print(obj.__dict__)     # {'x': 30, 'y': 20, 'z': '123'}
23 
24 # delattr
25 delattr(obj, 'z')
26 print(obj.__dict__)     # {'x': 30, 'y': 20}
 1 # 反射应用
 2 class FileControl:
 3 
 4     def run(self):
 5         while True:
 6             cmd = input('输入要进行功能(upload ---> 上传   download ---> 下载):').strip()
 7             if hasattr(self, cmd):
 8                 func = getattr(self, cmd)
 9                 func()
10             else:
11                 print('输入不合法')
12 
13     @staticmethod
14     def upload():
15         print('上传数据中...')
16 
17     @staticmethod
18     def download():
19         print('下载数据中...')
20 
21 
22 obj = FileControl()
23 obj.run()

猜你喜欢

转载自www.cnblogs.com/hexianshen/p/11950425.html