一,python中的方法没有重载
如果定义多个同名方法,则只有最后一个有效。
在其他语言中,可以通过形参列表区分但是python中不可以
测试代码如下:
class Tx:
def prints(self):
print('没有参数')
def prints(self,a):
print('参数为',a)
t=Tx()
t.prints(1)
结果如下:
参数为 1
二,方法的动态性
python是动态语言,我们可以动态的为类添加新的方法,也可以改变已有的方法
测试代码如下:
class Tips:
def work(self):
print('好好学习')
def play(a):
print('{0}在玩游戏'.format(a))
def work(a):
print('{0}在工作'.format(a))
Tips.play=play
Tips.work=work
p=Tips()
p.play() #Tips.play(p)
p.work()
结果如下:
<__main__.Tips object at 0x0000022931185B88>在玩游戏
<__main__.Tips object at 0x0000022931185B88>在工作
该代码的关键是将play与work看作对象,然后进行操作。相当于在Tips中创建一个类属性,存放函数的地址。
三,私有属性与私有方法
要点:(1)两个下划线开头的属性或方法为私有的,其他的为公共有的
(2)类内部可以直接访问私有属性和方法
(3)类外部不可以直接访问私有属性与方法
(4)在类外部可以通过_类名__私有属性名来访问私有属性
方法在本质上也是属性,只不过可以用()调用
测试代码如下:
class Employee:
__company='yzu'
def __init__(self,name,age):
self.name=name
self.__age=age #私有属性
def __fun(self): #私有方法
print('加油')
print(Employee.__company) #私有类属性,注意在类内部引用时,不需要加_类名,但是前面也要加类名
e=Employee('lhy',18)
print(e.name)
#print(e.age)
print(e._Employee__age)
print(dir(e))
#print(e.__fun)
print(e._Employee__fun())
print(Employee._Employee__company)
结果如下:
lhy
18
['_Employee__age', '_Employee__company', '_Employee__fun', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
加油
yzu
None
yzu
四,@property修饰器
它可以将一个方法的调用变成属性调用
测试代码如下:
class Employee:
@property
def salary(self):
return 10000
e=Employee()
print(e.salary)
#e.salary()错误
#e.salary=20000该方法中不可修改
结果如下:
10000
上面代码无法改变值,下面是改进代码
class Employee:
def __init__(self,salary):
self.__salary=salary
def get_salary(self):
return self.__salary
def set_salary(self,salary):
if 1000<salary<50000:
self.__salary=salary
else:
print('输入错误')
e=Employee(3000)
print(e.get_salary())
#e.set_salary(4000)
e.set_salary(-2000)
print(e.get_salary())
#改进
class Employee:
def __init__(self,salary):
self.__salary=salary
@property
def salary(self):
return self.__salary
@salary.setter
def salary(self,salary):
if 1000<salary<50000:
self.__salary=salary
else:
print('输入错误')
e=Employee(3000)
print(e.salary)
e.salary=-2000
print(e.salary)
结果如下:
3000
输入错误
3000
3000
输入错误
3000
五,面向对象三大特征
(1)封装:隐藏对象的属性和实现细节,只对外提供必要的方法
(2)继承:继承让子类具有父类的特征,提高代码重用性
(3)多态:同一种方法调用由于对象不同会产生不同的行为。
六,继承
语言格式:class 子类名(父类1,【父类2】。。。)
如果在类体中没有指定父类,则默认父类为object类,
object是所有类的父类,里面定义所有类默认实现的东西,如__new__()
一般来说,构造子类对象一般调用父类的构造函数。
对于父类的私有属性与私有方法,子类继承但不可以直接用。
测试代码如下:
class Person:
def __init__(self,name,age):
self.name=name
self.__age=age
def say_age(self):
print('年龄是{0}'.format(self.__age))
class Student(Person): #注意缩进,unindent
def __init__(self,name,age,score):
Person.__init__(self,name,age)#注意要加self
self.score=score
s=Student('lhy',18,60)
s.say_age()
print(Student.mro())#打印所属关系
#如果把age定为私有属性
print(s._Person__age)
结果如下:
年龄是18
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
18
七,类成员的继承与重写
(1)继承:子类继承父类除构造函数外的所有成员
(2)重写:子类中可以重新定义父类中的方法。
测试代码如下:
class Person:
def __init__(self,name,age):
self.name=name
self.__age=age
def say_age(self):
print('年龄是{0}'.format(self.__age))
class Student(Person): #注意缩进,unindent
def __init__(self,name,age,score):
Person.__init__(self,name,age)#注意要加self
self.score=score
def say_age(self):
print("{0}的年龄是{1}".format(self.name,self._Person__age))
s=Student('lhy',18,60)
s.say_age() #覆盖了父类的方法
结果为:
lhy的年龄是18
八,object根类
测试代码如下:
class Person:
def __init__(self,name,age):
self.name=name
self.__age=age
def say_age(self):
print('年龄是{0}'.format(self.__age))
print(dir(object))
s=Person('lhy',18)
print(dir(s))
s1=s.name
s2=s._Person__age
s3=s.say_age
print(type(s1))
print(type(s2))
print(type(s3))#方法也是属性,只不过是method属性,可以用()调用
结果如下:
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
['_Person__age', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'say_age']
<class 'str'>
<class 'int'>
<class 'method'>
九,__str__方法
该方法用来返回一个对象的描述,用print()方法时,会使用该方法
测试代码如下:
class Person:
def __init__(self,name):
self.name=name
s=Person('lhy')
print(s)
#若使用str
class Person1:
def __init__(self,name):
self.name=name
def __str__(self):
return '修改了' #不用return会报错
s=Person1('lhy')
print(s)
结果如下:
<__main__.Person object at 0x0000027D6CD2AD08>
修改了
十,多重继承与特殊属性
多重继承会将类的整体结构搞得复杂,应该避免使用
测试代码如下:
class A:
def a(self):
print('a')
def say(self):
print('aaa')
class B:
def b(self):
print('b')
def say(self):
print('bbb')
class C(A,B):
pass
c=C()
c.a()
c.b()
c.say()#由于继承时候A在前面
print(C.mro())#c不可以
print(c.__dict__)
print(c.__class__)
print(C.__bases__)
print(C.__base__)
print(C.__mro__)
print(A.__subclasses__())
结果如下:
a
b
aaa
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
{}
<class '__main__.C'>
(<class '__main__.A'>, <class '__main__.B'>)
<class '__main__.A'>
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
[<class '__main__.C'>]
十一,super()获取父类定义
在子类中,如果想获得父类方法时,可以通过super()来实现
super()代表父类的定义,不是父类的对象
测试代码如下:
class A:
def a(self):
print(self)
class B(A):
def say(self):
#A.a(self)
super().a()#与上语句相似
print(self)
#b=B()
#b.say()
B().say()
结果为:
<__main__.B object at 0x0000024E8A450548>
<__main__.B object at 0x0000024E8A450548>
十二,多态
多态是由于对象不同而产生不同行为
要点:(1)只有方法有多态,属性没有多态
(2)多态必须存在两个必要条件:继承与方法重写
测试代码如下:
class Man:
def eat(self):
print('吃饭行为')
class Chinese(Man):
def eat(self):
print('用筷子吃')
class English(Man):
def eat(self):
print('用刀叉吃')
class Indian(Man):
def eat(self):
print('用右手吃')
def maneat(m):
if isinstance(m,Man):
m.eat()
else:
print('不能吃饭')
maneat(Chinese())
maneat(English())
maneat(Indian)
maneat(Man())
结果为:
用筷子吃
用刀叉吃
不能吃饭
吃饭行为
十三,特殊方法与运算符重载
测试如下:
class Person:
def __init__(self,name):
self.name=name
def __add__(self, other):
if isinstance(other,Person):#检测是不是Person类
return "{0}__{1}".format(self.name,other.name)#这里的other其实是一个Person对象
else:
return "不能打印"
def __mul__(self, other):
if isinstance(other,int):
return self.name*3
else:
return "不能打印"
p1=Person('lhy')
p2=Person('zm')
c=p1+p2
print(c)
d=p1*3
print(d)
结果为:
lhy__zm
lhylhylhy
十四,对象的浅拷贝与深拷贝
测试代码如下:
import copy
class Phone:
def __init__(self,cpu,screen):
self.cpu=cpu
self.screen=screen
class Cpu:
pass
class Screen:
pass
#测试变量赋值
c=Cpu()
c2=c
print(c)
print(c2)
s=Screen()
print('测试浅拷贝')
p=Phone(c,s)#Phone(1,2)?
p1=copy.copy(p)
print(p,p.cpu,p.screen)
print(p1,p1.cpu,p1.screen)
print('测试深拷贝')
p2=copy.deepcopy(p)
print(p,p.cpu,p.screen)
print(p2,p2.cpu,p2.screen)
结果如下:
<__main__.Cpu object at 0x000001D7AFC3C748>
<__main__.Cpu object at 0x000001D7AFC3C748>
测试浅拷贝
<__main__.Phone object at 0x000001D7B0B99DC8> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
<__main__.Phone object at 0x000001D7AFC48288> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
测试深拷贝
<__main__.Phone object at 0x000001D7B0B99DC8> <__main__.Cpu object at 0x000001D7AFC3C748> <__main__.Screen object at 0x000001D7AFC40948>
<__main__.Phone object at 0x000001D7B0C23248> <__main__.Cpu object at 0x000001D7B0C23BC8> <__main__.Screen object at 0x000001D7B0C23C48>
十五,组合
is-a关系用继承
has-a关系用组合
测试代码如下:
class A1:
def a1(self):
print('aaa')
class B1(A1):
pass
B1().a1()
#组合
class A2:
def a2(self):
print('bbb')
class B2:
def __init__(self,a):
self.a=a
B2(A2()).a.a2()#这里B2中包含A2,然后将A2()的对象,传入B2中,用来创建a,所以a.a2()可以调用
结果如下:
aaa
bbb
十六,工厂模式实现
class CarFactory:
def create_car(self,brand):
if brand=='奔驰':
return BC()
elif brand=='比亚迪':
return BYD()
elif brand=='法拉利':
return FLL()
class BC:
pass
class BYD:
pass
class FLL:
pass
factory=CarFactory()
c1=factory.create_car('奔驰')
c2=factory.create_car(('比亚迪'))
十七,单例模式实现
class Dan:
__obj=None
init_flag=True
def __new__(cls, *args, **kwargs):
if cls.__obj==None:#忘加cls
cls.__obj=object.__new__(cls)
return cls.__obj
def __init__(self):
if Dan.init_flag==True:#忘加Dan
Dan.init_flag=False
print('执行了')
d1=Dan()
d2=Dan()
print(d1)
print(d2)
结果如下:
执行了
<__main__.Dan object at 0x0000021EB37C4B88>
<__main__.Dan object at 0x0000021EB37C4B88>