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')