python_面向对象进阶(7)
第1章 面向对象特性—继承(补充)
1.1 接口类、抽象类介绍
1.2 接口类
1.3 接口类应用过程
1.3.1 第一版:完成多种支付方式接口
1.3.2 第二版: 归一化设计,统一支付方式
1.3.3 第三版:野生程序员的乱搞
1.3.4 第四版:制定规范,统一方法名
1.3.5 第五版本:强制性制定规定
1.4 抽象类
1.4.1 解释:
1.4.2 为什么要有抽象类
1.4.3 抽象类实际应用理论
1.4.4 抽象类的使用方法
1.5 接口类和抽象类的区别
1.6 继承注意问题
第2章 面幸对象特征—多态
2.1 鸭子类
2.2 多态实例
第3章 面向对象特征—封装
3.1 封装定义
3.2 广益封装
3.3 狭义封装
3.3.1 特点
3.3.2 1)私有静态字段(静态变量)
3.3.3 私有字段外部调用方法
3.3.4 私有字段内部访问方式
3.3.5 2)私有普通变量(私有对象属性)
3.3.6 3)私有方法
3.3.7 4)私有成员实际应用
第4章 面向对象进阶
4.1 面向对象整体结构及成员
4.1.1 字段:
4.1.2 方法:
4.1.3 属性
4.2 @peroperty
4.2.1 将方法变为属性
4.2.2 私有属性的外部显示
4.2.3 @age.setter修改私有属性
4.2.4 自动触发的三要素
4.2.5 peroperty匹配的三种方法
4.3 类方法:
4.3.1 @classmethod
4.3.2 静态方法直接引用@staticmethod
4.4 *****getattr()反射
4.4.1 在类中
4.4.2 在对象中
4.4.3 在模块中
4.4.4 在当前模块中
4.4.5 通过字符串去到 类名 中取值
4.4.6 hasattr/ getattr/ setattr/ delattr
4.5 *****hasattr()
4.6 其他方法
4.6.1 isinstance()
4.6.2 issubclass()
4.7 __len__
4.8 __hash__
4.9 __str__
4.10 __repr__
4.11 ***__call__
4.12 __eq__
4.13 __del__
4.14 ****__new__
4.15 __item__
第1章 面向对象特性—继承(补充)
1.1 接口类、抽象类介绍
解释:接口类和抽象类是一种规范,写代码时的规范
1.2 接口类
继承有两种用途:
l 继承基类的方法,并且做出自己的改变或者扩展(代码重用)
l 声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能
实践中,继承的第一种含义意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合。
继承的第二种含义非常重要。它又叫“接口继承”。
接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。
归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
1.3 接口类应用过程
1.3.1 第一版:完成多种支付方式接口
class QQpay:
def pay(self,money):
print('您已经通过qq支付了%s元' %money)
class Alipay:
def pay(self,money):
print('您已经通过支付宝支付了%s元' %money)
a = QQpay()
b = Alipay()
a.pay(100)
b.pay(200)
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
您已经通过qq支付了100元
您已经通过支付宝支付了200元
缺点:
若果十个支付方式.py()支付方式不统一,写了十次太麻烦
1.3.2 第二版: 归一化设计,统一支付方式
class QQpay:
def pay(self,money):
print('您已经通过qq支付了%s元' %money)
class Alipay:
def pay(self,money):
print('您已经通过支付宝支付了%s元' %money)
def pay(obj,money):
obj.pay(money)
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
您已经通过qq支付了100元
您已经通过支付宝支付了200元
缺点:确实统一了支付方式,但是新增接口时并无任何提示,及相关接口的保护
1.3.3 第三版:野生程序员的乱搞
class QQpay:
def pay(self,money):
print('您已经通过qq支付了%s元' %money)
class Alipay:
def pay(self,money):
print('您已经通过支付宝支付了%s元' %money)
class Wechatpay:
def fukuan(self,money):
print('您已经通过微信支付了%s元' %money)
def pay(obj,money):
obj.fukuan(money) ###野生程序员更改了支付方式的代码
c = Wechatpay()
pay(c,200)
a = QQpay() ###原接口已经被改变,不能使用
pay(a,100)
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
您已经通过微信支付了200元
Traceback (most recent call last):
File "D:/python/untitled2/python_7/lession2.py", line 61, in <module>
pay(a,100)
File "D:/python/untitled2/python_7/lession2.py", line 55, in pay
obj.fukuan(money)
1.3.4 第四版:制定规范,统一方法名
class Payrole:
def pay(self):pass
class QQpay(Payrole):
def pay(self,money):
print('您已经通过qq支付了%s元' %money)
class Alipay(Payrole):
def pay(self,money):
print('您已经通过支付宝支付了%s元' %money)
class Wechatpay(Payrole):
def pay(self,money):
print('您已经通过微信支付了%s元' %money)
def pay(obj,money):
obj.pay(money)
缺点:归一化了付款接口,但是谁来都可以随意改动
1.3.5 第五版本:强制性制定规定
解释:from abc import ABCMeta,abstractclassmethod #从abc文件中引用两个模块
如果不用pay方法就会报错:
例:
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 抽象类 接口类 规范和约束 metaclass指定的是一个元类
@abstractmethod
def pay(self):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
def pay(obj,money):
obj.pay(money)
a = Wechatpay()
b = QQpay()
c = Alipay()
pay(a,100)
pay(b,200)
pay(c,201)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
使用微信支付了100元
使用qq支付了200元
使用支付宝支付了201元
1.4 抽象类
1.4.1 解释:
与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
1.4.2 为什么要有抽象类
如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类就是从一堆类中抽取相同的内容而来的,内容包括数据属性和函数属性。
1.4.3 抽象类实际应用理论
比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子……..你永远无法吃到一个叫做水果的东西。
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案
1.4.4 抽象类的使用方法
l 组合
面向对象的组合用法,软件重用的重要方式除了继承之外还有另外一种方式,即:组合
组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合
例1):攻击类
class Person:
def __init__(self,nickname,sex,hp,ad):
self.nickname = nickname
self.sex = sex
self.hp = hp
self.ad = ad
def attack(self,p1):
p1.hp -= self.ad
print('%s攻击了%s,%s还剩%s血量'%(self.nickname,p1.nickname,p1.nickname,p1.hp))
def weapon_attack(self,wea):
# 武器类的对象封装到人的对象中当做一个属性.就叫做组合.
self.weapon = wea
class Weapon:
def __init__(self,name,att):
self.name = name
self.att = att
def Aux_attack(self,p,p1):
p1.hp -= self.att
print('%s利用%s打了%s%s滴血,%s还剩%s滴血' %(p.nickname,self.name,p1.nickname,self.att,p1.nickname,p1.hp))
# alex = Person('alex','男',100,20)
# barry = Person('太白','男',200,50)
# axe = Weapon('斧子',30)
# barry.weapon_attack(axe)
# barry.weapon.Aux_attack(barry,alex)
# axe.Aux_attack(alex)
# alex.attack(barry)
# alex.attack(barry)
例2):计算类
圆环是由两个圆组成的,圆环的面积是外面圆的面积减去内部圆的面积。圆环的周长是内部圆的周长加上外部圆的周长。
这个时候,我们就首先实现一个圆形类,计算一个圆的周长和面积。然后在"环形类"中组合圆形的实例作为自己的属性来用
from math import pi
class Circle:
'''
定义了一个圆形类;
提供计算面积(area)和周长(perimeter)的方法
'''
def __init__(self,radius):
self.radius = radius
def area(self):
return pi * self.radius * self.radius
def perimeter(self):
return 2 * pi *self.radius
circle = Circle(10) #实例化一个圆
area1 = circle.area() #计算圆面积
per1 = circle.perimeter() #计算圆周长
print(area1,per1) #打印圆面积和周长
class Ring:
'''
定义了一个圆环类
提供圆环的面积和周长的方法
'''
def __init__(self,radius_outside,radius_inside):
self.outsid_circle = Circle(radius_outside)
self.inside_circle = Circle(radius_inside)
def area(self):
return self.outsid_circle.area() - self.inside_circle.area()
def perimeter(self):
return self.outsid_circle.perimeter() + self.inside_circle.perimeter()
ring = Ring(10,5) #实例化一个环形
print(ring.perimeter()) #计算环形的周长
print(ring.area()) #计算环形的面积
例3)
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python课程
class BirthDate:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
class Couse:
def __init__(self,name,price,period):
self.name=name
self.price=price
self.period=period
class Teacher:
def __init__(self,name,gender,birth,course):
self.name=name
self.gender=gender
self.birth=birth
self.course=course
def teach(self):
print('teaching')
p1=Teacher('egon','male',
BirthDate('1995','1','27'),
Couse('python','28000','4 months')
)
print(p1.birth.year,p1.birth.month,p1.birth.day)
print(p1.course.name,p1.course.price,p1.course.period)
'''
运行结果:
27
python 28000 4 months
'''
当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
1.5 接口类和抽象类的区别
抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。
1.6 继承注意问题
l 多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
l 接口隔离原则
使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。
l 方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
第2章 面幸对象特征—多态
2.1 鸭子类
Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”
2.2 多态实例
python对于一些相似的功能不用强制规定直接约定俗成,默认支持多态,自带多态
class F1:
pass
class S1(F1):
def show(self):
print 'S1.show'
class S2(F1):
def show(self):
print 'S2.show'
# 由于在Java或C#中定义函数参数时,必须指定参数的类型
# 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
# 而实际传入的参数是:S1对象和S2对象
def Func(F1 obj):
"""Func函数需要接收一个F1类型或者F1子类的类型"""
print obj.show()
s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
Python伪代码实现Java或C#的多态
Python伪代码实现java C#多态
第3章 面向对象特征—封装
3.1 封装定义
封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。
所以,在使用面向对象的封装特性时,需要:
l 将内容封装到某处
l 从某处调用被封装的内容
3.2 广益封装
class Pesrson:
country = 'China'
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(self.name)
#创建了两个对象
p1 = Pesrson('wang',100)
p2 = Pesrson('li',200)
p1.func()#封装到对象中的属性是一种封装
3.3 狭义封装
定义:也称私有性封装
3.3.1 特点
只要类执行,将类的内容加载到内存时,发现“__变量名” ,自动将其转化成"_类名__变量名",所以找不到。
私有静态字段,类的内部都可以访问,父类以及类的外部都不能访问
3.3.2 1)私有静态字段(静态变量)
实例:私有静态变量调用结果
class Pesrson:
country = 'China' #共有静态字段/变量
__name == 'lili'##私有静态字段/变量
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(self.name)
print(Pesrson.__name)
p1 = Pesrson('wang',100)
p2 = Pesrson('li',200)
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
Traceback (most recent call last):
File "D:/python/untitled2/python_7/lession2.py", line 79, in <module>
class Pesrson:
File "D:/python/untitled2/python_7/lession2.py", line 81, in Pesrson
__name == 'lili'##私有静态字段/变量
NameError: name '_Pesrson__name' is not defined
在类的外部谁都不能调用
3.3.3 私有字段外部调用方法
class Pesrson:
country = 'China' #共有静态字段/变量
__name = 'lili'##私有静态字段/变量
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(self.name)
p1 = Pesrson('wang',100)
p2 = Pesrson('li',200)
print(Pesrson.__dict__['_Pesrson__name'])
print(p1._Pesrson__name)
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
lili
lili
注意:虽然可以访问但工作中没有这样访问的
3.3.4 私有字段内部访问方式
解释:对于私有字段,在子类派生类也不可访问父类的私有静态字段,只能在本类使用
class Person:
country = 'China' #共有静态字段/变量
__name = 'lili'##私有静态字段/变量
__age = 23
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
return self.__name
p1 = Person('liu',19)
print(p1.func())
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
lili
3.3.5 2)私有普通变量(私有对象属性)
class Person:
def __init__(self,name,age):
self.name = name #公有普通字段
self.__age = age #私有普通字段
p1 = Person('wang',18)
print(p1.name)
print(p1.__age)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
Traceback (most recent call last):
File "D:/python/untitled2/python_7/lession2.py", line 112, in <module>
print(p1.__age)
wang
AttributeError: 'Person' object has no attribute '__age'
3.3.6 3)私有方法
class Person:
def __init__(self,name,age):
self.name = name #公有普通字段
self.__age = age #私有普通字段
def __func(self):#私有方法
print(666)
p1 = Person('wang',18)
print(p1.name)
p1.__func()
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
Traceback (most recent call last):
File "D:/python/untitled2/python_7/lession2.py", line 116, in <module>
p1.__func()
AttributeError: 'Person' object has no attribute '__func'
wang
3.3.7 4)私有成员实际应用
对只想让类内部使用的成员,要设置成私有成员
例1):密码加密方法
class Person:
def __init__(self,username,password):
self.username = username
self.__password = self.__encryption(password)
def __encryption(self,pwd):
'''
加密处理
:param pwd:
:return:
'''
return '%s xyz123' % pwd
p1 = Person('wang','123')
print(p1._Person__password)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
123 xyz123
例2):
类的执行顺序:有先找__init__
class A:
def __init__(self):
self.func()
def func(self):
print('in A')
class B(A):
def func(self):
print('in B')
b = B()
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
in B
执行逻辑:
b è B(A) è A() è __init__ èfunc() è B.func() è print('in B')
例3)
class A:
def __init__(self):
self.__func()
def __func(self):
print('in A')
class B(A):
def __func(self):
print('in B')
b = B()
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
in A
执行逻辑:
b è B(A) è A() è __init__ èself.__func() == self._A__func() è A.func() è print('in A')
第4章 面向对象进阶
4.1 面向对象整体结构及成员
4.1.1 字段:
普通字段和静态字段
4.1.2 方法:
普通方法和属性
1)普通:一般是由对象调用的 init
class A:
name = 'lili'
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(666)
p1 = A('li',19)
print(p1.name)
print(p1.age)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
li
19
4.1.3 属性
例一
BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
体质指数(BMI)=体重(kg)÷身高^2(m)
EX:70kg÷(1.75×1.75)=22.86
class People:
def __init__(self,name,weight,height):
self.name = name
self.__weight = weight
self.__height = height
def bmi(self):
return self.__weight /self.__height **2
p1 = People('wang',75,1.78)
print(p1.bmi())
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
23.671253629592222
4.2 @peroperty
4.2.1 将方法变为属性
解释:property 将你的 ‘一些方法伪装为属性,虽然在代码是哪个没有提高,让其看起来合乎情理’
例:
class People1:
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
p2 = People1('wang',75,1.78)
print(p2.bmi)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
23.671253629592222
4.2.2 私有属性的外部显示
class People1:
def __init__(self,name,weight,height,age):
self.name = name
self.__weight = weight
self.__height = height
self.__age = age
def age(self):
return self.__age
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
<class 'float'>
<bound method People1.age of <__main__.People1 object at 0x00000000021D8B00>>
加@property 后
class People1:
def __init__(self,name,weight,height,age):
self.name = name
self.__weight = weight
self.__height = height
self.__age = age
@property
def age(self):
return self.__age
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
<class 'float'>
16
4.2.3 @age.setter修改私有属性
class People1:
def __init__(self,name,weight,height,age):
self.name = name
self.__weight = weight
self.__height = height
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self,new_age):
if type(new_age) == int:
self.__age = new_age
else:
return '请输入一个整数'
p1 = People1('lili',45,1.6,23)
print(p1.age)
p1.age = 22
print(p1.age)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
23
22
4.2.4 自动触发的三要素
m 方法名相同
m 对方法赋值
m 调用方法setter
4.2.5 peroperty匹配的三种方法
l getattr(object, name, default=None)
l setattr(x, y, v) 设置增加或修改
l delattr(x, y)
class People1:
def __init__(self,name,weight,height,age):
self.name = name
self.__weight = weight
self.__height = height
self.__age = age
@property
def age(self):
return self.__age
@age.setter
def age(self,new_age):
if type(new_age) == int:
self.__age = new_age
else:
return '请输入一个整数'
@age.deleter
def age(self):
print(666)
p1 = People1('lili',45,1.6,23)
print(p1.age) #触发@property 方法
p1.age = '1234' #触发@aage.setter 装饰器方法
del p1.age #触发 @age.deleter装饰的方法
print(p1.age)
一个属性只能对应一个值
class People:
def __init__(self,name,age,sex):
self.name = name
self.__age = age
self.__sex = sex
def age(self):
return self.__age
p1 = People('wang','25','男')
print(p1.name)
print(p1.age)
输出
C:\python3\python.exe D:/python/untitled2/lianxi/lianxi.py
wang
<bound method People.age of <__main__.People object at 0x00000000021F8940>>
输出年龄
class People:
def __init__(self,name,age,sex):
self.name = name
self.__age = age
self.__sex = sex
@property
def age(self):
return self.__age
p1 = People('wang','25','男')
print(p1.name)
print(p1.age)
练习:水果折扣价格
class Goods:
def __init__(self,name,origin_price,discount):
self.name = name
self.__origin_price = origin_price
self.__discount = discount
@property
def price(self):
return self.__origin_price*self.__discount
@price.setter
def price(self,new_price):
self.__origin_price = new_price
obj1 = Goods('apple',5,0.8)
print(obj1.price)
obj1.price = 8
print(obj1.price)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
4.0
6.4
4.3 类方法:
一般用类名直接调用
有些情况对于类内部的方法,无需对象直接调用,而用类名直接调用即可
例1:(对象调用)
class Goods:
__discount = 0.8
def __init__(self,name,origin_price):
self.name = name
self.__origin_price = origin_price
@property
def price(self):
return self.__origin_price * Goods.__discount
def discount(self,new_discount):
Goods.__discount = new_discount
p1 = Goods('apple',5)
print(p1.price)
p1.discount(0.85)
print(p1.price)
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
4.0
4.25
4.3.1 @classmethod
例2 (类名调用)
cls 默认接受类名本身
class Goods:
__discount = 0.8
def __init__(self,name,origin_price):
self.name = name
self.__origin_price = origin_price
@property
def price(self):
return self.__origin_price * Goods.__discount
@classmethod
def discount(cls,new_discount):
Goods.__discount = new_discount
p1 = Goods('apple',5)
Goods.discount(0.85)
print(p1.price)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
4.25
4.3.2 静态方法直接引用@staticmethod
不用类cls或者对象self 传值,直接调用即可
class A:
def __init__(self):
pass
@staticmethod
def login(username,password):
print(username,password)
A.login('wang',134)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
wang 134
4.4 *****getattr()反射
概念:python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
4.4.1 在类中
解释:通过字符串去到 类名 中获取值。
特殊:在python中,一切皆对象,凡是通过 什么.什么 ,通过 反射都能取到。
要求:输入字段即可获取字段
class A:
role = 'Teacher'
def func(self):
print(666)
eval exec用法注意:写死的时候可以用
普通方法:
class A:
role = 'Teacher'
def func(self):
print(666)
msg = input('>>')
print(A.__dict__[msg])
输出:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
>>role
Teacher
升级后:反射
class A:
role = 'Teacher'
def func(self):
print(666)
# msg = input('>>')
# print(A.__dict__[msg])
print(getattr(A,'role'))
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
Teacher
完整形式:
class A:
role = 'Teacher'
def func(self):
print(666)
msg = input('>>')
print(getattr(A,msg))
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
>>role
Teacher
4.4.2 在对象中
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'))
print(hasattr(obj,'say_hi'))
#获取属性
n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()
print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
#设置属性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))
#删除属性
delattr(obj,'age')
delattr(obj,'show_name')
delattr(obj,'show_name111')#不存在,则报错
print(obj.__dict__)
对实例化对象的示例
4.4.3 在模块中
#一个模块中的代码
def test():
print('from the test')
"""
程序目录:
module_test.py
index.py
当前文件:
index.py
"""
# 另一个模块中的代码
import module_test as obj
#obj.test()
print(hasattr(obj,'test'))
getattr(obj,'test')()
4.4.4 在当前模块中
import sys
def s1():
print 's1'
def s2():
print 's2'
this_module = sys.modules[__name__]
hasattr(this_module, 's1')
getattr(this_module, 's2')
4.4.5 通过字符串去到 类名 中取值
class A:
role = 'Teacher'
def func(self):
print(666)
msg = input('>>')
getattr(A,msg)(111)
输出
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
>>func
666
4.4.6 hasattr/ getattr/ setattr/ delattr
解释:通过字符串到类中判断是否存
l hasattr(object,name)
l getattr(object, name, default=None)
l setattr()
l delattr() 删除
应用实例:
class BlackMedium:
feature='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_house(self):
print('%s 黑中介卖房子啦,傻逼才买呢,但是谁能证明自己不傻逼' %self.name)
def rent_house(self):
print('%s 黑中介租房子啦,傻逼才租呢' %self.name)
b1=BlackMedium('万成置地','回龙观天露园')
#检测是否含有某属性
print(hasattr(b1,'name'))
print(hasattr(b1,'sell_house'))
#获取属性
n=getattr(b1,'name')
print(n)
func=getattr(b1,'rent_house')
func()
# getattr(b1,'aaaaaaaa') #报错
print(getattr(b1,'aaaaaaaa','不存在啊'))
#设置属性
setattr(b1,'sb',True)
setattr(b1,'show_name',lambda self:self.name+'sb')
print(b1.__dict__)
print(b1.show_name(b1))
#删除属性
delattr(b1,'addr')
delattr(b1,'show_name')
delattr(b1,'show_name111')#不存在,则报错
print(b1.__dict__)
4.4.7 *****hasattr()
通过字符串操作对象进行判断,先判断有没有值,再用getattra取值
class A:
role = 'Teacher'
def __init__(self,name,age):
self.name = name
self.age = age
a1 = A('wang',18)
print(hasattr(a1,'name'))
print(hasattr(a1,'alex'))
输出
C:\python3\python.exe D:/python/untitled2/lianxi/练习2.py
True
False
结合getatter用法
class A:
role = 'Teacher'
def __init__(self,name,age):
self.name = name
self.age = age
a1 = A('wang',18)
print(hasattr(a1,'name'))
print(hasattr(a1,'alex'))
print(getattr(a1,'name'))
4.5 其他方法
4.6 ****__new__
解释:创建对象的根源
源码解释:
def __new__(cls, *more): # known special case of object.__new__
""" Create and return a new object. See help(type) for accurate signature. """
pass
案例分析
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A, *args, **kwargs)
a = A()
print(a.x)
设计模式:单例模式(一个类只能实例化一个对象)
class A:
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
obj = object.__new__(cls)
cls.__instance = obj
return cls.__instance
4.7 ***__call__
解释:对象加()自动执行__call__方法
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
4.8 isinstance()
对象属不属于这个类是不是输入这个类的派生类
class A: pass
class B(A): pass
abj = B()
print(isinstance(abj,B)) #true
print(isinstance(abj,A)) #true
4.9 issubclass()
第一类是第二个类的后代就是true
class A: pass
class B(A): pass
abj = B()
print(issubclass(B,A)) #true
4.10 __len__
解释: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)
4.11 __hash__
解释:能不能hash 看对象中有没有__hash__
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))
4.12 __str__
类中如果有__str__方法,打印或者str() 即可执行str
class A:
def __init__(self):
pass
def __str__(self):
return '太白'
a = A()
print(a)
print('%s' % a)
4.13 __repr__
解释:如果一个类中定义了__repr__方法,那么在repr(对象) 时,默认输出该方法的返回
class A:
def __init__(self):
pass
def __repr__(self):
return 'lili'
a = A()
print(repr(a))
print('%r'%a)
4.14 __eq__
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)
4.15 __del__
析构方法:自动执行
析构方法,当对象在内存中被释放时,自动触发执行。
注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class A:
def __init__(self):
self.a =1
self.b =2
def __del__(self):
print(222)
return 666
obj1 = A()
解释:
C:\python3\python.exe D:/python/untitled2/python_7/lession2.py
222
4.16 __item__
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('sb')
print(f1.__dict__)
f1['age']=18
print(f1.__dict__)
f1['age1']=19
print(f1.__dict__)
del f1.age1
print(f1.__dict__)
del f1['age']
print(f1.__dict__)
f1['name']='alex'
print(f1.__dict__)
输出
C:\python3\python.exe D:/python/untitled2/lianxi/练习2.py
{'name': 'sb'}
{'name': 'sb', 'age': 18}
{'name': 'sb', 'age': 18, 'age1': 19}
del obj.key时,我执行
{'name': 'sb', 'age': 18}
del obj[key]时,我执行
{'name': 'sb'}
{'name': 'alex'}
python_面向对象进阶(7)的更多相关文章
- Python_面向对象进阶
isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() isi ...
- Python全栈开发【面向对象进阶】
Python全栈开发[面向对象进阶] 本节内容: isinstance(obj,cls)和issubclass(sub,super) 反射 __setattr__,__delattr__,__geta ...
- day26、面向对象进阶:多态、封装、反射
一.多态 什么是多态: 类的继承有两层意义:1.改变 2.扩展 多态就是类的这两层意义的一个具体的实现机. 即:调用不同类实例化的对象,下的相同的方法,实现的过程不一样 python中的标准类型就是多 ...
- Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)
Python开发[第七篇]:面向对象 详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇) 上一篇<Python 面向对象(初级篇)> ...
- python基础——面向对象进阶下
python基础--面向对象进阶下 1 __setitem__,__getitem,__delitem__ 把对象操作属性模拟成字典的格式 想对比__getattr__(), __setattr__( ...
- python基础——面向对象进阶
python基础--面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 ...
- 周末班:Python基础之面向对象进阶
面向对象进阶 类型判断 issubclass 首先,我们先看issubclass() 这个内置函数可以帮我们判断x类是否是y类型的子类. class Base: pass class Foo(Base ...
- Python面向对象进阶和socket网络编程-day08
写在前面 上课第八天,打卡: 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __i ...
- 铁乐学python_day24_面向对象进阶1_内置方法
铁乐学python_day24_面向对象进阶1_内置方法 题外话1: 学习方法[wwwh] what where why how 是什么,用在哪里,为什么,怎么用 学习到一个新知识点的时候,多问问上面 ...
随机推荐
- LIS(最长上升子序列)的三种经典求法
求最长上升子序列的三种经典方案: 给定一个长度为 \(N\) 的数列,求它数值单调递增的子序列长度最大为多少.即已知有数列 \(A\) , \(A=\{A_1,A_2....A_n\}\) ,求 \( ...
- linux网络配置及IP绑定
在学习时,参考了这篇文章:http://blog.csdn.net/collection4u/article/details/14127671:在这篇文章中作者讲述了VMware中虚机的三种网络模式: ...
- 数据结构之 图论---bfs(邻接表)
数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索( ...
- 织梦dedecms页面中增加二维码功能的实现方法
本文介绍了在dedecms中增加二维码功能的实现方法,有时需要在dedecms页面增加二维码,方便手机用户访问,有需要的朋友参考下. 本节内容: dedecms中增加二维码功能 1.打开/incl ...
- java面试题基础
hashMap原理 hashMap是数组+链表的数据结构 每一个数组元素中都是一个链表 通过记录的关键字key.hashCode()%数组的长度 来决定记录在数组中的存储位置 对于数组的同一个存储位置 ...
- springboot web项目搭建
1.选择spring initializr 2.填写应用名称及设置相关配置,建议使用默认配置即可 3.选择相关技术,我们现在web技术 4.填写项目名称 5.项目文件结构如下 6.直接运行 java ...
- 关于JQuery获取元素索引值的理解
举例: <html> <body> <div id="text"> <div> <a><span>标题一&l ...
- 机器学习 Hidden Markov Models 3
Viterbi Algorithm 前面我们提到过,HMM的第二类问题是利用HMM模型和可观察序列寻找最有可能生成该观察序列的隐藏变量的序列.简单来说,第一类问题是通过模型计算生成观察序列的概率,而第 ...
- 移动端网页巧用 margin和padding 的百分比实现自适应
一个基础却又容易混淆的css知识点 本文依赖于一个基础却又容易混淆的css知识点:当margin/padding取形式为百分比的值时,无论是left/right,还是top/bottom,都是以父元素 ...
- HTTP Status 500 - javax.servlet.ServletException: java.lang.NoClassDefFoundError: junit/framework/Test解决方法
java代码 package webViewer; import java.io.*; import junit.framework.Test; import com.aspose.words.*; ...