Python面向对象(继承、多态、封装、传参方式、鸭子类型、局部变量)

Python面向对象:

1.类的属性可以通过实例化对象动态添加

2.传参方式:
1)所谓模子就是类抽象的

2)对象 = 类名()

3)过程:
(1)类名():首先会创造出一个对象,创建了一个self变量
(2)调用init方法,类名括号里的参数会被这里接收
(3)执行init方法
(4)返回self对象,self就是一个特殊的大字典

# __init__,调用,执行
class A:
    count = 0
    def __init__(self):
        A.count += 1
f1 = A()
f2 = A()
print(f1.count)  # 2
print(f2.count)  # 2
class A:
	def __init__(self, a):
		self.a = a

	def func(self):
		print(self.a)
		print(self.b)
		print(self.c)

a = A(2)
a.b = 44  # 可以给实例化对象动态添加类的属性
a.c = 55
a.func()  # 2  44  55
print(a.__dict__)  # {'a': 2, 'b': 44, 'c': 55}  查看实例化对象的所有属性
print(A.__dict__)  # {'__module__': '__main__', '__init__' ... ...} 查看类的所有方法

3.类中的局部变量,可变数据类型修改是共享的,不可变数据类型修改仅限于实例化对象

class A:
	name = ['wang']  # 可变数据类型
	age = 22         # 不可变数据类型
	def __init__(self, *args):  # args : ()
		self.a = args[0]

	def func(self):
		# 类的局部变量,函数内可以这样调用
		print(A.name, A.age)  # ['wang']  22
		print(self.a)
		print(self.b)
		print(self.c)
print('-----', A.name)  # ----- ['wang']
a = A(2)
a.b = 44  # 可以给实例化对象动态添加类的属性
a.c = 55
a.func()  # 2  44  55
a.name[0] = 'liu'  # 修改类中的变量
a.age = 18
# 可变数据类型修改是共享的(类和实例化对象共享),不可变数据类型修改不共享,只在自己的实例化对象有效
print(a.name, a.age)      # ['liu']  18
print(A.name, A.age)      # ['liu']  22
print(a.__dict__)  # {'a': 2, 'b': 44, 'c': 55, 'age': 18}  查看实例化对象的所有属性
# 查看类的所有方法和属性
print(A.__dict__)  # {'__module__': '__main__', 'name': ['liu'], 'age': 22, '__init__' ...}

类中的局部变量可以通过类名来访问

class A:
	name = ['wang']  # 可变数据类型
	age = 22         # 不可变数据类型
	def __init__(self, *args):  # args : ()
		self.a = args[0]

	def func(self):
		# 类的局部变量,函数内可以这样调用
		print(A.name, A.age)  # ['wang']  22
		print(self.a)
		print(self.b)
		print(self.c)
print('-----', A.name)  # ----- ['wang']

4.一个类的定义不一定要__init__

5.面向对象的三大特性:继承,多态,封装

6.组合:一个对象的属性值是另外一个类的对象,类的实例化对象可以做类的属性

7.类的继承:

# 一个类可以被多个子类继承
# 一个类也可以继承多个父类
class A:pass #父类,基类,超类
class B:pass #父类,基类,超类
class A_son(A,B):pass#子类,派生类
print(A_son.__bases__)  # (<class '__main__.A'>, <class '__main__.B'>)
print(A.__bases__)      # (<class 'object'>,) 默认继承隐藏超类object

多继承:一个类继承多个父类 路径:A -> B -> C

# 多继承
class A:
    def func(self):print('A')
class B:
    def func(self):print('B')
class C:
    def func(self): print('C')
class D(A,B,C):
    pass
d = D()
d.func() #离的最近的func方法,应该是A的

钻石继承:被继承的两个类继承同一个类

# 钻石继承 : 被继承的两个类继承同一个类
class A:
    def func(self):print('A')
class B(A):
    def func(self):print('B')
class C(A):
    def func(self): print('C')
class D(B,C):
    pass
# 继承路径 D -> B -> C -> A
d = D()
d.func() #离的最近的func方法,因该是B的,若B中没有func该找C的若B,C中都没有,该找A的

漏斗继承:被继承的两个类分别继承不同的类

class A:
    def func(self):print('A')
class E:
    def func(self):print('E')
class B(A):
    def func(self):print('B')
class C(E):
    def func(self): print('C')
class D(B,C):
    pass
print(D.mro())  #可记录继承路径 D -> B -> A -> C -> E
d = D()
d.func() #离的最近的func方法,应该是B的,若B中没有func,该找A的,若A中也都没有该找C的

(1)经典类深度优先 python2.7新式经典共存,新式类要继承object
(2)新式类广度优先 python3.7只有新式类,默认继承object, mro, super方法只有新式类中有,super只在python3.7中有
(3)super的本质:不是直接找父类,而是根据调用者的节点位置的广度优先顺序来的

菱形继承:
在这里插入图片描述

# 菱形继承:继承的两个类分别继承不同的类,不同的类又继承同一个类
# 类的先后顺序不可以交换
class F:
    def func(self): print('F')
class A(F):
    def func(self):print('A')
class B(A):
    def func(self):print('B')
class E(F):
    def func(self): print('E')
class C(E):
    def func(self):print('C')
class D(B,C):
    pass
print(D.mro())  #可记录继承路径 D -> B -> A -> C -> E -> F
d = D()
d.func() #离的最近的func方法,应该是B的,若B中没有func,找A的,A没找C,C没找E,都没找F

接口类和抽象类:

1、抽象类规范
一般情况下单继承能实现的功能都是一样的,所以在父类中可以有一些简单的基础实现
多继承的情况,由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中

2、抽象类还是接口类:面向对象的开发规范
(1)python中没有接口类:java里有接口Interface这个概念
(2)python中自带多继承,所以我们直接用class来实现了接口类
(3)python中支持抽象类:一般情况下单继承不能实例化
(4)多态python天生支持多态(动态强类型的语言)

3、鸭子类型
(1)不崇尚根据继承所得来的相似
(2)我只是自己实现自己的代码就可以了
(3)如果两个类刚好相似,并不产生父类的子类的兄弟关系,而是鸭子类型
例:tuple list 这种相似是自己写代码时约束的,而不是通过父类约束的
(4)优点:松耦合 每个相似的类之间都没有影响

接口类
python不支持,默认是多继承,所有方法都必须不能实现

# 接口类
from abc import abstractmethod,ABCMeta
class Payment(metaclass=ABCMeta):     # 元类 默认的元类 type
    @abstractmethod
    def pay(self):
        raise NotImplemented          # 没有实现这个方法

class Wechat:
    def pay(self, money):
        print('微信支付了%s元'%money)
class Alipay:
    def pay(self, money):
        print('支付宝支付了%s元'%money)
class Applepay:
    def fuqian(self, money):        # 这个类没有pay这个方法
        print('Applepay支付了%s元'%money)

def pay_for(pay_obj, money):        # 统一支付入口
    pay_obj.pay(money)

wechat = Wechat()
ali = Alipay()
apple_pay = Applepay()
pay_for(wechat, 200)     # 微信支付了200元
pay_for(ali, 300)        # 支付宝支付了300元
# pay_for(apple_pay, 100)  # 报错 'Applepay' object has no attribute 'pay'

抽象类:
python支持,不支持多继承

from abc import abstractmethod,ABCMeta
class Swim_Animal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):
        pass
swim_animal = Swim_Animal()
class Walk_Animal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):
        pass
walk_wnimal = Walk_Animal()
class Fly_Animal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):
        pass
fly_animal = Fly_Animal()

class Tiger(Walk_Animal,Swim_Animal):
    def walk(self):
    	pass
    def swim(self):
        pass
class Swan(Walk_Animal,Fly_Animal,Swim_Animal):pass

tiger = Tiger()
tiger.walk()

静态方法:
在完全面向对象的程序中,如果一个函数既和对象没有关系也和类没有关系那么就用staticmethod将这个函数变成一个静态方法

class Login:
    def __init__(self,name,password):
        self.name = name
        self.pwd  = password
    def login(self):
        pass
    @staticmethod
    def get_usr_pwd():   #没有默认参数,就像函数一样
        usr = input('用户名:')
        pwd = input('密码:')
        Login(usr,pwd)
Login.get_usr_pwd()

封装:
1、广义上面向对象的封装:代码的保护,面向对象的思想本身就是一种封装
2、只让自己的对象能调用自己类的方法
3、狭义上的封装 – 面向对象三大特性
4、属性和方法都藏起来,不让你看见

Testcase:
1.下面代码输出结果为: # 20, 10, None

a = 10
b = 20
def func(a, b):
	print(a, b)
c = func(b, a)
print(c)  # 20, 10, None 无返回值return

2.求字符串中数字的和:

# 正则匹配求和  + 1-n次  ? 0-1次  * 0-n次
# 方法一
import re
s='123.33sdhf3424.34fdg323.324asda123'
p = r'\d+\.?\d*'
r = re.findall(p, s)   # ['123.33', '3424.34', '323.324', '123']
print(sum([float(i) for i in r]))  # 3993.994
# 方法二
import re
s='123.33sdhf3424.34fdg323.324asda123'
p = r'\d+\.?\d*'
r = re.findall(p, s)
r = '+'.join(r)
print(r)        # '123.33+3424.34+323.324+123'
print(eval(r))  # 3993.994  eval()函数求值

3.输出值为list类型的key组成一个list:

# 输出字典中值为list的key
d={'k1':'v1','k2':[1,2,3],('k','3'):{1,2,3}}
ret = [k for k in d if type(d[k]) is list]
print(ret)

4.匹配方式

# strings字符串的筛选
# http开头的https开头的
# IP地址
import re
# if self.strings[k][1]
# 要不要匹配HTTP和HTTPS的,是开头match匹配还是全部search匹配
s = 'http://www.baidu.com'
s1 = 'https://www.163.com'
s3 = '/.,[,;],;ahm,ldshs'
# 从头开始匹配,开头为https和http
if re.match(r"http|https", s3):
	print(re.match(r"http|https", s3))
else:
	print('can not match')

# 匹配到是把IP提取出来,还是把原字符串存储下来
s2 = 'fsdf172.123.7.2sdfsg'
if re.findall(r'\d+\.\d+\.\d+\.\d+', s3):
	print(re.findall(r'\d+\.\d+\.\d+\.\d+', s3))
	print(re.findall(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', s3)) # 返回一个list
else:
	print('22222')

猜你喜欢

转载自blog.csdn.net/weixin_42563968/article/details/108548914
今日推荐