多态: 拥有多种形态, 一对多
效果图: len()函数可以获取list类、str类等的长度。 原因 这些类中含有 __len__特殊方法
代码:
one_list = [1,2,3,4,5,6] print(type(one_list)) str1 = 'hello' print(type(str1)) print(len(one_list)) print(len(str1))
转载于:https://www.cnblogs.com/FlyingLiao/p/11335595.html
一、Python多态
1.对象多态
对象多态:在继承体系中,定义时的类型和运行时的类型不一样,此时就构成多态
以下是Python伪代码实现Java或C的多态:
class A(object): def test(self): print('A test') class B(A): def test(self): print('B test') class C(A): def test(self): print('C test') def go(a): """ 接收A类或其子类实例 :param a: :return: """ a.test() if __name__ == '__main__': go(A()) go(B()) go(C())
执行结果:
由此可见,go函数接收A类或其子类对象,无论是传递A类对象、B类对象、C类对象,方法都可以正常执行, 此时便构成了对象的多态。
2.类多态
类多态:指通过@classmethod形式多态地构造对象,而不是使用Python默认的__init__构造器
需求:实现一套MapReduce流程,用于统计目录下所有文件的总行数,代码如下:
""" 知识要点: 1.接口 抽象 继承 2.生成器 3.map reduce 4.多线程 5.通过@classmethod形式批量创建对象 """ import os import threading class GenericInputData(object): """ 通用输入抽象类 抽象方法由子类实现 """ def read(self): raise NotImplementedError @classmethod def generate_inputs(cls, config): raise NotImplementedError class FileInputData(GenericInputData): """ 文件输入类 """ def __init__(self, path): super().__init__() self.path = path def read(self): return open(self.path, 'r', encoding='utf-8').read() @classmethod def generate_inputs(cls, config): dir_path = config['dir_path'] for file_name in os.listdir(dir_path): yield cls(os.path.join(dir_path, file_name)) class GenericWorker(object): """ 通用Worker抽象类 抽象方法由子类实现 """ def __init__(self, input_data): self.input_data = input_data self.result = None def map(self): raise NotImplementedError def reduce(self, other): raise NotImplementedError @classmethod def generate_workers(cls, input_class, config): for input_data in input_class.generate_inputs(config): yield cls(input_data) class LineCountWorker(GenericWorker): """ 统计文件换行符Worker类 """ def map(self): content = self.input_data.read() self.result = content.count('\n') def reduce(self, other): self.result += other.result def execute(workers): threads = [threading.Thread(target=w.map) for w in workers] for thread in threads: thread.start() thread.join() first, rest = workers[0], workers[1:] for other in rest: first.reduce(other) return first.result def map_reduce(input_class, worker_class, config): gen_workers = worker_class.generate_workers(input_class, config) workers = list(gen_workers) return execute(workers) if __name__ == '__main__': result = map_reduce(FileInputData, LineCountWorker, {'dir_path': 'temp'}) print(result)
由此可见,在Python中,不仅可以通过__init__构造器创建对象,也可以通过@classmethod形式多态地构建对象。
python 多态实例
# coding:utf-8
"""
多态(英语:Polymorphism),是指面向对象程序运行时,相同的消息可能会送给多个不同的类之对象,
而系统可依据对象所属类,引发对应类的方法,而有不同的行为。
简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作称之。
在面向对象程序设计中,多态一般指子类型多态(Subtype polymorphism)。
上面的定义有点让初学者费解,黄哥用“打开”这个动作来描述面向对象的多态。
"打开",可以是打开门,打开窗户,打开书等等。"打开"这个动作,碰到不同的对象门,窗户,书,有不同的行为模式。
这个就是多态。
本文由黄哥python培训,黄哥所写
黄哥python远程视频培训班
https://github.com/pythonpeixun/article/blob/master/index.md
黄哥python培训试看视频播放地址
https://github.com/pythonpeixun/article/blob/master/python_shiping.md
"""
# 例1
class Door(object):
def open(self):
print "打开门"
class Windows(object):
def open(self):
print "打开窗户"
class Book(object):
def open(self):
print "打开书"
lst = [Door(), Windows(), Book()]
for item in lst:
item.open()
# 例2 一般用继承来说明多态的例子
class Animal:
def __init__(self, name):
self.name = name
def talk(self):
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
return 'Meow!'
class Dog(Animal):
def talk(self):
return 'Woof! Woof!'
animals = [Cat('Missy'),
Cat('Mr. Mistoffelees'),
Dog('Lassie')]
for animal in animals:
print animal.name + ': ' + animal.talk()
# 例3 python 内置有很多多态的应用
# 同样的 +号 可以用在不同的对象相加,体现(相仿:指相加这个事情)了多态的功能。
print 1 + 2
print "hello" + '黄哥'
# len 函数传不同的参数,也体现了多态的功能。
print len("黄哥python培训")
print len([2, 4, 5, 7])
# 工程应用
# 一个简单的日志记录函数,用判断实现的,重构为面向对象多态来实现。
#如果有大量的判断语句,就可以用多态来实现。
def log_msg(log_type):
msg = 'Operation successful'
if log_type == 'file':
log_file.write(msg)
elif log_type == 'database':
cursor.execute('INSERT INTO log_table (MSG) VALUES ('?')', msg)
#重构
class FileLogger(object):
def log(self, msg):
log_file.write(msg)
class DbLogger(object):
def log(self, msg):
cursor.execute('INSERT INTO log_table (MSG) VALUES ('?')', msg)
def log_msg(obj):
msg = 'Operation successful'
obj.log(msg)
python多态和一些内置方法
什么是多态:
多态指的是同一种类型的事物,不同的形态
多态的目的:
“多态”也称之为“多态性”,目的是为了在不知道对象具体类型的情况下,同一对象调用方法的规范(比如:名字)
多态的“表现形式之一”就是继承:
先抽象,在继承
父类:定制一套统一的规范。(比如:方法的统一)
子类:遵循父类的统一规范。 (比如:子类遵循父类方法名的统一)
注意:在python中不会强制限制子类, 必须要遵循父类的规范,所以出现了抽象类。
# 动物类
class Animal:
def eat(self):
pass
def speak(self):
pass
class Pig(Animal):
def eat(self):
print('吧唧 吧唧...')
class Cat(Animal):
def eat(self):
print('喵喵喵...')
class Dag(Animal):
def eat(self):
print('汪汪汪...')
a1 = Pig()
a2 = Cat()
a3 = Dag()
a1.eat()
a2.eat()
a3.eat()
抽象类
什么是抽象类?
在python内置中的abc模块中,有一个抽象类。
抽象类的作用:
让子类必须遵循父类的编写规范
如何实现抽象类
父类需要继承abc模块中metaclass = abc.ABCMeta
在父类的方法中,需要装饰上 abc.abseractmethod
注意: 在python中不推荐使用抽象类
自己不虚按照父类的方法编写规范,缺一不可。
(只要父类中有几个抽象方法,子类就必须要定义几个)
import abc
# 父类
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod
def eat(self):
pass
@abc.abstractmethod
def speak(self):
pass
class Pig(Animal):
def eat(self):
print('biajibiaji ')
def speak(self):
print('哼哼哼')
a1 = Pig()
a1.eat()
a1.speak()
鸭子类型
什么是鸭子类型:
不同的对象,只要长得像鸭子, 动作行为像鸭子,那它就是鸭子
鸭子是多态的一种表现形式
为什么要有鸭子类型:不同对象,先抽象出相同的类型的方法, 给他们制定一套统一的规范,
所有的类,在定义是都按照统一的规范进行书写
多态的三种表现形式
1、继承父类 ***
2、继承抽象类 ***
3、鸭子类型 **** 耦合度低, 程序可扩展性高
注意:在python中,强烈推荐使用鸭子类型
lass Pig:
def eat(self):
print('bia唧...')
def speak(self):
print('哼哼哼...')
# 猫类
class Cat:
def eat(self):
print('咬ji 咬ji....')
def speak(self):
print('喵喵喵...')
# 狗类
class Dog:
def eat(self):
print('舔 ji 舔ji...')
def speak(self):
print('汪汪汪...')
dog = Dog()
pig = Pig()
cat = Cat()
# dog.speak()
# pig.speak()
# cat.speak()
# 多态之炫技
def SPEAK(animal):
animal.speak()
# SPEAK(dog)
# SPEAK(pig)
# SPEAK(cat)
classnethod和staticmethod
classnethod和staticmethod都是python解释器的内置装饰器(重要)
classmethod:
是一个装饰器,给在类内部定义方法中装饰。 将类内部的方法变为“类的绑定方法”
staticmethod:
翻译:静态方法
是一个装饰器,在给类内部定义方法中装饰,将类内部的方法变为“非法绑定方法”
对象的绑定方法:
由对象来调用,由谁来调用,会将谁(对象)当做第一个参数传入
类的绑定方法:由类来调用,由谁来调用,会将谁(类)当做第一个参数传入
非绑定方法:
可以由对象或类来调用,谁来调用都是一个普通方法(普通函数), 方法需要传入几个参数,就要传入几个
class DB:
__data = 'haowuliaoa'
def __init__(self, user, pwd, role):
self.user = user
self.pwd = pwd
self.role = role
# 查看数据
@classmethod
def check_db(cls, user, pwd, role):
obj = cls(user, pwd, role)
# 查看数据前,必须要通过校验
if obj.user == 'jinyi' and obj.pwd == '123' and obj.role == 'admin':
print('检验通过')
print(cls.__data)
return cls.__data
else:
print('验证不通过')
DB.check_db('jinyi', '123', 'admin')
class Foo:
@staticmethod
def func(res):
print(res)
obj = Foo()
# 对象调用非绑定方法
obj.func(123)
# 类调用非绑定方法
Foo.func(123)
isinstance与issubclass
isinstance与issubclass是python的内置模块
isinstance: 判断一个对象是否是另一个对象的实例
如果是:True
如果不是:False
issubclass: 判断一个类是否是另一个类的子类
如果是:Ture
如果不是:False
class Feacher:
pass
class Sub(Feacher):
pass
class Foo:
pass
print(issubclass(Foo, Feacher))
print(issubclass(Sub, Feacher))
反射
反射指的是通过“字符串”对对象的属性进行操作
hasattr:通过“字符串”判断对象的属性或方法是否存在
getattr:通过“字符串”获取对象的属性或方法
setattr:通过“字符串”设置对象的属性或方法
delattr:通过“字符串”删除对象的属性或方法
注意:反射的四个方法是python中内置的
class Foo:
def __init__(self, x, y):
self.x = x
self.y = y
obj = Foo(10, 20)
# hasattr: 通过 “字符串” 判断对象的属性或方法是否存在。
# 判断
print(hasattr(obj, 'x'))
# getattr: 通过 “字符串” 获取对象的属性或方法。
# 查
print(getattr(obj, 'y'))
res = getattr(obj, 'q', '不存在')
print(res)
# setattr: 通过 “字符串” 设置对象的属性或方法。
# 增 改
setattr(obj, 'q', 30)
print(getattr(obj, 'q'))
# delattr: 通过 “字符串” 删除对象的属性或方法。
delattr(obj, 'q')
print(getattr(obj, 'q', '没有了'))