文章目录
一、方法的重载二、方法的动态性三、私有属性四、@property装饰器(一)使用装饰器调用方法(二)使用get和set修改属性(三)使用@property和set修改属性
五、面向对象的三大特征说明(封装、继承和多态)(一)继承1. 成员继承2.方法的重写3.object根类4.重写__str__()方法5.多重继承6.mro()7.super()获得父类定义
(二)同一方法调用多态
六、特殊方法和运算符重载七、特殊属性八、对象的浅拷贝和深拷贝九、组合十、设计模式(一)工厂模式的实现(二)单例模式的实现
一、方法的重载
python中没有方法的重载。在其他语言中,可以定义多个重名的方法,只要保证方法签名唯一即可。方法签名包含3个部分:方法名、参数数量、参数类型。而在python中,如果定义了多个同名方法,那么只有最后一个有效,即方法可以重载。
class person:
def say_hi(self
):
print("hello")
def say_hi(self
,name
):
print("{0},hello".format(name
))
p1
=person
()
p1
.say_hi
()
二、方法的动态性
python是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类已有的方法。具体例子如下:
class Person:
def work(self
):
print("努力!")
def play_game(s
):
print("{0}在玩游戏".format(s
))
Person
.play
=play_game
p
=Person
()
p
.work
()
p
.play
()
三、私有属性
私有属性和私有方法,能够实现对象的封装,让外人不可随意查看。
就像电脑一样,只需要会用,不需要知道内部的工作原理。
注:方法本质上也是属性,只不过是通过()执行而已。要点: ①两个下划线开头的属性是私有属性:__私有属性名;其他的命名方法为公共属性; ②类内部可以直接访问私有属性(方法):类名.__私有属性名 ③类外部不能直接访问私有属性(方法),但可以通过“对象名._类名__私有属性(方法)名”访问私有属性(方法)
class Employee:
__company
='百战'
def __init__(self
,name
,age
):
self
.name
=name
self
.__age
=age
def __work(self
):
print("{0} ,please work hard!".format(self
.__age
))
print(Employee
.__company
)
e
=Employee
("何旯",18)
print(e
._Employee__age
)
e
._Employee__work
()
print(e
._Employee__company
)
print(dir(e
))
四、@property装饰器
(一)使用装饰器调用方法
含义:@property可以将一个方法的调用方式变成“属性调用”使用方法:在方法的前一行,写上@property优点:调用方法时,不需要在后面加()了,像调用属性一样:对象名.方法名
class Empolyee:
def salary(self
):
return 10000
emp1
=Employee
()
print(emp1
.salary
())
class Empolyee:
@
property
def salary(self
):
return 10000
emp1
=Employee
()
print(emp1
.salary
)
(二)使用get和set修改属性
class Employee:
def __init__(self
,name
,salary
):
self
.__name
=name
self
.__salary
=salary
def get_salary(self
):
return self
.__salary
def set_salary(self
,salary
):
if 10000<salary
<50000:
self
.__salary
=salary
else:
print("输入错误!")
emp1
=Employee
('高',30000)
print(emp1
.get_salary
())
emp1
.set_salary
(-20000)
print(emp1
.get_salary
())
emp1
.set_salary
(40000)
print(emp1
.get_salary
())
(三)使用@property和set修改属性
class Employee:
def __init__(self
,name
,salary
):
self
.__name
=name
self
.__salary
=salary
@
property
def salary(self
):
return self
.__salary
def set_salary(self
,salary
):
if 10000<salary
<50000:
self
.__salary
=salary
else:
print("输入错误!")
emp1
=Employee
('高',30000)
print(emp1
.salary
)
emp1
.set_salary
(-20000)
print(emp1
.salary
)
emp1
.set_salary
(40000)
print(emp1
.salary
)
五、面向对象的三大特征说明(封装、继承和多态)
python是面向对象语言。面向对象语言都有三大特性:封装(隐藏)、继承和多态。
封装(隐藏)
含义:隐藏对象的属性和实现细节,只对外暴露“相关调用方法”。实现方式:私有属性、私有方法
继承
继承可以让子类具有父类的特性,提高了代码的重用性原有父类设计不变的情况下,子类可以增加新的功能,或者改进已有算法
多态
含义:由于对象不同,同一个方法的调用会产生不同的行为例子:中国人用筷子吃饭,美国人用刀叉吃饭等
(一)继承
已有的类:父类 新的类:子类(派生类)
1. 成员继承
语法格式:class 子类类名(父类1[,父类2,…]):类体如果没有指定父类,则默认父类为object类。object类中定义了一些所有类共有的默认实现,比如__new__()定义子类时,必须在其构造函数中调用父类的构造函数。
class Person:
def __init__(self
,name
,age
):
self
.name
=name
self
.__age
=age
def say_age(self
):
print("不知道")
class Student(Person
):
def __init__(self
,name
,age
,score
):
Person
.__init__
(self
,name
,age
)
Student
.score
=score
stu1
=Student
("高",18,80)
print(stu1
.name
)
print(stu1
.age
)
print(stu1
.__Person__age
)
stu1
.say_age
()
2.方法的重写
class Person:
def __init__(self
,name
,age
):
self
.name
=name
self
.__age
=age
def say_age(self
):
print("我的年龄为:",self
.__age
)
def say_introduce(self
):
print("我的名字为:",self
.name
)
class Student(Person
):
def __init__(self
,name
,age
,score
):
Person
.__init__
(self
,name
,age
)
Student
.score
=score
stu1
=Student
("高",18,80)
stu1
.say_age
()
stu1
.say_introduce
()
class Student(Person
):
def __init__(self
,name
,age
,score
):
Person
.__init__
(self
,name
,age
)
Student
.score
=score
def say_introduce(self
):
print("报告老师,我的名字是:{0}".format(self
.name
))
stu1
.say_introduce
()
3.object根类
object根类:object根类是所有类的父类。学习object类的结构,对深入学习python有好处。使用dir()可以查看类的属性
4.重写__str__()方法
object有一个__str__()方法,用于返回对于“对象的描述”str()方法需要搭配printstr()方法可以重写
class Student:
def __init__(self
,name
):
self
.name
=name
p
=Student
("gao")
print(p
)
class Student:
def __init__(self
,name
):
self
.name
=name
def __str__(self
):
return "名字是{0}".format(self
.name
)
p
=Student
("gao")
print(p
)
5.多重继承
python支持多重继承,一个子类可以有多个父类,但是这样会被“类的整体层次”搞得异常复杂,应尽量避免使用。
class A:
def aa(self
):
print("aa")
class B:
def bb(self
):
print("bb")
class C(A
,B
):
def cc(self
):
print("cc")
c
=C
()
c
.cc
()
c
.aa
()
c
.bb
()
6.mro()
mro():通过类的方法mro()或者类的属性__mro__可以输出类的继承结构,或者说层次结构。
例子如下:
class A:pass
class B(A
):pass
class C(B
):pass
print(C
.miro
())
输出结果为:
由于python支持多重继承,所以父类中如果有相同名字的方法,在子类没有指定父类名时,会按照“从左到右”的顺序搜索。
class A:
def aa(self
):
print("aa")
def say(self
):
print("say AAA!")
class B:
def bb(self
):
print("bb")
def say(self
):
print("say BBB!")
class C(A
,B
):
def cc(self
):
print("cc")
c
=C
()
print(C
.mro
())
c
.say
()
7.super()获得父类定义
在子类中,如果想要获得父类的方法时,需要通过super()来实现
class A:
def say(self
):
print("A:",self
)
class B(A
):
def say(self
):
A
.say
(self
)
print("B:",self
)
B
().say
()
class B(A
):
def say(self
):
super().say
()
print("B:",self
)
B
().say
()
(二)同一方法调用多态
多态是指同一方法调用,由于对象不同可能产生不同行为。注: 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
())
六、特殊方法和运算符重载
python的运算符实际上是通过调用对象的特殊方法实现的。比如:
a
=20
b
=30
c
=a
+b
d
=a
.__add_
(b
)
print('c=',c
)
print('d=',d
)
每个运算符实际上都对应了相应的方法,统计如下: 这解释了为什么字符串也可以进行±*等等操作
常见的特殊方法统计如下:
运算符重载(实质是方法的重载)
class Person:
def __init__(self
,name
):
self
.name
=name
def __add__(self
,other
):
if isinstance(other
,Person
):
return "{0}--{1}".format(self
.name
,other
.name
)
else:
return "不是同类对象,不能相加"
def __mul__(self
,other
):
if isintance
(other
,int):
return self
.name
*other
else:
return "传入的数据不是整数类型,不能相乘"
p1
=Person
("GA")
p2
=Person
("ca")
f
=p1
+p2
print(f
)
print(f
*3)
七、特殊属性
obj.dict:获得类的属性字典
class c:
def __init__(self
,age
):
self
.age
=age
g
=c
(20)
print(g
.__dict__
)
obj.class:获得对象属于的类
class a:
def say(self
):
print("不错")
class c(a
):
def __init__(self
,age
):
self
.age
=age
g
=c
(20)
print(g
.__class__
)
obj.bases:当有多个父类时,将对象的父类的地址放在元组中
class a:
def say(self
):
print("不错")
class b:
def say(self
):
print("很好")
class c(a
,b
):
def __init__(self
,age
):
self
.age
=age
g
=c
(20)
print(g
.__bases__
)
obj.base:当只有单个父类时,输出对象的父类的地址obj.mro:类层次结构obj.subclass():子类列表
class a:
def say(self
):
print("不错")
class c(a
):
def __init__(self
,age
):
self
.age
=age
g
=c
(20)
print(a
.__subclass__
())
八、对象的浅拷贝和深拷贝
变量赋值:形成两个变量(可以理解为标签),实质指向同一个对象(那么两个变量的地址仍然不变)浅拷贝:只拷贝了源对象,没有拷贝儿子和孙子,拷贝对象和源对象仍然指向同一个儿子和孙子。因此源对象和拷贝对象的地址不同,但是子对象的地址相同深拷贝:不仅拷贝了源对象,还拷贝了儿子和孙子。因此,源对象和拷贝对象的地址不同,其子对象的地址也不同
九、组合
继承:是“is a”的关系,如狗是动物组合:是“has a”的关系,如手机拥有cpu
class A:
def say_a1(self
):
print("a1")
class B(a
):
pass
b
=B
()
b
.say_a1
class C:
def __init__(self
,a
):
self
.a
=a
class D:
def say_d1(self
,a
):
print("我是{0}".format(a
))
c
=C
(D
())
c
.D
.say_d1
()
十、设计模式
(一)工厂模式的实现
含义:设计模式是面向对象语言特有的内容,是我们在面临某一类问题时候的固定做法。比较流行的是GOF(Goup Of Four)模式。工厂模式:能够实现创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一的管理和控制 例子如下:
class CarFactory:
def create_car(self
,brand
):
if brand
=="奔驰":
return Benz
()
elif brand
=="宝马":
return BNW
()
elif brand
=="比亚迪":
return BYD
()
else:
return "未知品牌,无法创建"
class Benz:
pass
class BNW:
pass
class BYD:
pass
factory
=CarFactory
()
c1
=factory
.create_car
("奔驰")
c2
=factory
.create_car
("比亚迪")
(二)单例模式的实现
核心作用:确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。优点:当一个对象的对象的产生需要比较多的资源,如读取配置文件、产生其他依赖对象时,可以产生一个“单例对象”,然后永久驻留于内存中,从而极大地降低开销。
class MySingleton:
__obj
=None
__init__flag
=True
def __new__(cls
,*args
,**kwargs
):
if cls
.__obj
==NONE
:
cls
.__obj
=object.__new__
(cls
)
return cls
.__obj
def __init__(self
,name
):
if MySingleton
.__init__flag
==True:
print("init...")
self
.name
=name
MySingleton
.__init__flag
==False
a
=MySingleton
("aa")
b
=MySingleton
("bb")
print(a
)
print(b
)
class CarFactory:
__new__
=None
__init__flag
=True
def __new__(cls
,*args
,**kwargs
):
if cls
.__obj
==NONE
:
cls
.__obj
=object.__new__
(cls
)
return cls
.__obj
def __init__(self
):
if CarFactory
.__init__flag
==True:
print("init CarFactory...")
CarFactory
.__init__flag
==False
def create_car(self
,brand
):
if brand
=="奔驰":
return Benz
()
elif brand
=="宝马":
return BNW
()
elif brand
=="比亚迪":
return BYD
()
else:
return "未知品牌,无法创建"
class Benz:
pass
class BNW:
pass
class BYD:
pass
factory1
=CarFactory
()
c1
=factory1
.create_car
("奔驰")
c2
=factory1
.create_car
("比亚迪")
factory2
=CarFactory
()
print(factory1
)
print(factory2
)