方法没有重载(与其他语言不同)
定义多个重名方法,只有最后一个有效
方法的动态性
可以为类、对象添加新方法,或者修改已有的方法
class Person:
def work(self):
print("work hard")
# 创建类
p = Person()
# 调用类中的方法
p.work()
- 若只是调用类外部的方法是无法调用的
class Person:
def work(self):
print("work hard")
def play_game(s):
print("{0}is palying games".format(s))
p = Person()
p.work()
p.play__game()
把要加的方法加到类中,这样就可以了
Person.play = play_game
p = Person()
p.work()
p.play() # 实际上是person.play(p)
- 修改原方法
class Person:
def work(self):
print("work hard")
def work2(s):
print("make money")
# 记住修改方法时新方法不用加括号
Person.work = work2
p = Person()
p.work()
私有属性
原非私有情况
class Employee():
def __init__(self,name,age):
# 属性
self.name = name
self.age = age
e = Employee("Celia",23)
print(e.name)
print(e.age)
可通过这种方法访问私有属性
class Employee():
def __init__(self,name,age):
# 属性
self.name = name
self.__age = age
e = Employee("Celia",23)
print(e.name)
print(e._Employee__age)
私有方法
- 调用私有方法
class Employee():
def __work(self):
print("work hard, make money")
e._Employee__work()
- 类内部用私有方法调用私有属性
class Employee():
def __init__(self,name,age):
# 属性
self.name = name
self.__age = age
def __work(self):
print("work hard, make money")
print("age{0}".format(self.__age))
e._Employee__work()
class Employee():
# 类的私有类对象
__company = "Celia"
def __work(self):
print(Employee.__company)
# 在类外部调用私有类对象
print(Employee._Employee__company)
@property装饰器
作用:将一个方法的调用变成属性的调用,用来增加get、set方法
举例
- 简单示例
传统调用:
class Employee:
def salary(self):
return 10000
emp1 = Employee()
emp2.salary()
用@property
class Employee:
@property
def salary(self):
return 10000
emp1 = Employee()
print(emp1.salary)
# 不能设置方法
# emp1.salary = 20000
- 调用私有属性——最好把类中的属性设为私有,否则容易出错。然后利用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 1000 < salary < 500000:
self.__salary = salary
else:
print('wrong data! The number should be in 1000-50000')
emp1 = Employee("Celia", 20000)
print(emp1.get_salary())
emp1.set_salary(2000) # 输入2000
print(emp1.get_salary())
若用@property就不用加get和set方法了。也简化了调用
class Employee:
def __init__(self, name, salary):
self.__name = name
self.__salary = salary
@property
def salary(self): # 代替了get salary
return self.__salary
@salary.setter # 再加上一个装饰器,表示针对salary属性的一个设置
def salary(self, salary): # 代替了set salary
if 1000 < salary < 500000:
self.__salary = salary
else:
print('wrong data! The number should be in 1000-50000')
emp1 = Employee("Celia",30000)
print(emp1.salary) # 读取
emp1.salary = 2000 # 赋值
print(emp1.salary)
# 输出结果
30000
2000
面向对象的三大特征说明(封装、继承、多态)
封装:将细节封装,只留下调用和赋值供用户使用(调用界面越简单越好)。
继承: 一个子类可以有多个直接的父类
继承举例:
- 虽然Student类当中什么也没有,但是继承自Person类的方法。可以调用
# 继承
# 定义一个Person类
class Person:
def say_age(self):
print("age, I don't know")
# Student类继承Person类
class Student(Person):
pass
# Student-->Person-->object类(最原始类)
print(Student.mro())
s = Student()
s.say_age()
- 调用父类初始化方法(必须显式调用父类初始化方法,否则解释器不会调用)
①查询子类是否包含了父类的内容
②私有的方法和属性属性子类继承了,但是不可以随便调用
③如何调用父类的私有属性及方法呢
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age # 看看私有属性能否调用
def say_age(self):
print("age, I don't know")
# Student类继承Person类
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age)
self.score = score
# Student-->Person-->object类(最原始类)
print(Student.mro())
s = Student("Celia", 23,100)
s.say_age()
print(s.name) # 查询子类是否包含了父类的内容
print(s.age) # 私有的方法属性子类继承了,但是不可以随便调用
print(dir(s)) # 可用此方法看看子类是否真的继承了父类的方法
print(s._Person__age) # 可以这样调用私有属性
测试方法的重写(常用)
原方法:
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age # 私有属性
def say_age(self):
print("age:", self.__age)
def say_introtuce(self):
print("my name:{0}".format(self.name))
class Student(Person):
# 与原父类方法相同
def __init__(self,name,age,score):
Person.__init__(self,name,age)
self.score = score
s = Student("Celia",18,90)
s.say_age()
s.say_introtuce()
**重写方法"say_introduce":**在调用子类创建对象时,子类重写的方法可以覆盖父类的方法
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age # 私有属性
def say_age(self):
print("age:", self.__age)
def say_introtuce(self):
'''重写了父类的方法'''
print("Teacher! my name is:{0}".format(self.name))
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age)
self.score = score
s = Student("Celia",18,90)
s.say_age()
s.say_introtuce()
查看类的继承层次结构
通过类的方法mro()或者类的属性__mro__可以输出这个类的继承层次结构
举例练习:
class A: pass
class B(A): pass
class C(B): pass
print(C.mro())
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
# C继承自B-A-Obgect
dir()内置函数
可查看属性
object根类
是所有类的父类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def say_age(self):
print(self.name, "的年龄是:", self.age)
obj = object()
print(dir(obj))
s2 = Person("celia", 23)
print(dir(s2))
['__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__']
['__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__', 'age', 'name', 'say_age']
重写obgect的__str__()
class Person: # 默认继承obgect类
def __init__(self, name):
self.name = name
# 重写
def __str__(self):
return "name is :{0}".format(self.name)
p = Person("celia")
print(p)
多重继承(子类可以具备多个父类的特点)
一般情况尽量避免使用,方式结构过于复杂易造成网状结构
super()获取父类的定义(可以将定义看作是代码)
在子类中,如果想要获取父类的方法,可以用super()来做
注意:不是获取父类的对象
练习:测试super()
首先,我们可以这样做:
class A:
def say(self):
print("A", self)
class B:
def say(self):
A.say(self)
print("B", self)
B().say()
或者用super()
class A:
def say(self):
print("A", self)
class B:
def say(self):
# A.say(self)
super().say()
print("B", self)
B().say()
多态
- 由于对象的不同,产生不同的行为
- 多态是方法的多态,不是属性的
- 两个必要条件:继承、方法的重写
class Man:
def eat(self):
print("hungry and eat")
class Chinese(Man):
def eat(self):
print("chinese eating")
class English(Man):
def eat(self):
print("English eating")
class Indian(Man):
def eat(self):
print("using hand")
def maneat(m):
if isinstance(m,Man): # m如果是Man的子类的话,调用方法
m.eat()
else:
print("cannot eat")
maneat(Chinese())
maneat(English())
特殊方法和运算符重载
使自定义的类生成的对象能够使用运算符进行操作
运算符函数需要什么去网上搜
这里以加法、乘法为例进行运算符重载举例:
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 isinstance(other, int):
return self.name*other
else:
return "不能相乘"
p1 = Person("Celia")
p2 = Person("lucy")
x = p1+p2
print(x)
y = p1*p2
print(y)
Z = p1*3
print(Z)
Celia--lucy
不能相乘
CeliaCeliaCelia
特殊属性
对象的浅拷贝与深拷贝
浅复制
import copy
class MobilePhone:
def __init__(self,cpu,screen):
self.cpu = cpu
self.screen = screen
class CPU:
def calculate(self):
print("算个12345")
print("cpu对象:", self)
class Screen:
def show(self):
print("显示一个好看的画面")
print("screen对象:",self)
# 测试变量赋值
c1 = CPU()
c2 = c1
print(c1)
print(c2)
# 测试浅复制
s1 = Screen()
m1 = MobilePhone(c1, s1)
m2 = copy.copy(m1)
# 打印不同对象(手机)及其下的cpu,screen看看是否相同
print(m1, m1.cpu, m1.screen)
print(m2, m2.cpu, m2.screen)
发现对象不同,但是cpu和screen都一样,但只复制了对象本身,没有其”子子孙孙“
<__main__.CPU object at 0x00000198D22AEB70>
<__main__.CPU object at 0x00000198D22AEB70>
<__main__.MobilePhone object at 0x00000198D22AEF28> <__main__.CPU object at 0x00000198D22AEB70> <__main__.Screen object at 0x00000198D22AEEF0>
<__main__.MobilePhone object at 0x00000198D22AFB38> <__main__.CPU object at 0x00000198D22AEB70> <__main__.Screen object at 0x00000198D22AEEF0>
深复制
import copy
class MobilePhone:
def __init__(self,cpu,screen):
self.cpu = cpu
self.screen = screen
class CPU:
def calculate(self):
print("算个12345")
print("cpu对象:", self)
class Screen:
def show(self):
print("显示一个好看的画面")
print("screen对象:",self)
# 测试变量赋值
c1 = CPU()
c2 = c1
print(c1)
print(c2)
# 测试浅复制
print("测试浅复制")
s1 = Screen()
m1 = MobilePhone(c1, s1)
m2 = copy.copy(m1)
# 打印不同对象(手机)及其下的cpu,screen看看是否相同
print(m1, m1.cpu, m1.screen)
print(m2, m2.cpu, m2.screen)
# 测试深复制
print("测试深复制")
m3 = copy.deepcopy(m1)
print(m1, m1.cpu, m1.screen)
print(m3, m3.cpu, m3.screen)
输出的cpu和screen都是与m1不同的
测试深复制
<__main__.MobilePhone object at 0x00000233D609EEF0> <__main__.CPU object at 0x00000233D609EB70> <__main__.Screen object at 0x00000233D609EF28>
<__main__.MobilePhone object at 0x00000233D6095B00> <__main__.CPU object at 0x00000233D89B9A90> <__main__.Screen object at 0x00000233D89B9F60>
组合
“has a”关系是组合:手机由cpu
“is a”关系是继承:狗是一个动物
# 测试组合
class A1:
def say_a1(self):
print("yes ok")
# 用组合:把A1的对象作为自己的属性
class A2:
def __init__(self,a):
self.a = a
a1 = A1()
a2 = A2(a1)
a2.a.say_a1()
设计模式——工厂模式
class CarFactory:
def create_car(self, brand):
if brand == "奔驰":
return Benz()
elif brand == "宝马":
return BMW()
elif brand =="比亚迪":
return BYD()
else:
return "未知品牌无法创建"
class Benz:
pass
class BMW:
pass
class BYD:
pass
factory = CarFactory()
c1 = factory.create_car("奔驰")
print(c1)
c2 = factory.create_car("比亚迪")
print(c2)
<__main__.Benz object at 0x000001FC842DEEF0>
<__main__.BYD object at 0x000001FC842DFB38>
设计模式——单例模式
- 确保一个类只有一个实例(对象),减少系统的开销
- 通常需要重写new方法,和构造器构造方法
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:
print("init……")
self.name = name
MySingleton.__init_flag = False
a = MySingleton("aa")
b = MySingleton("bb")
print(a)
print(b)
c = MySingleton("cc")
print(c)
拜师教育学员文章:作者:1212-王同学,
转载或复制请以 超链接形式 并注明出处 拜师资源博客。
原文地址:《python学习笔记——面向对象celia2》 发布于2020-09-11
评论 抢沙发