方法没有重载
1、在其他语言中,可以定义多个同名的方法
2、Python中方法的参数没有声明类型,参数的数量也可以由可变参数控制,因此Python中没有方法的重载
3、定义一个方法即可有多种调用方式,相当于实现了其他语言中的方法的重载
4、定义多个同名方法时,只有最后一个有效
方法的动态性
Python是动态语言,可以动态地为类添加新方法,或者动态地修改类的已有的方法
class Person:
def work(self):
print("努力工作!")
def play_game(a):
print("{}在玩游戏".format(a))
def work2(n):
print("努力赚大钱,努力工作!")
Person.play = play_game
p = Person()
p.work()
p.play() #解释器解释为Person.play(p)
Person.work = work2 #二者形参数量要对应
p.work()
运行结果为:
努力工作!
<__main__.Person object at 0x00000287ABF64CF8>在玩游戏
努力赚大钱,努力工作!
私有属性和私有方法
1、Python对于类的成员没有严格的访问控制权限,这与其他面向对象语言有区别
2、关于私有属性和私有方法有如下要点:
①通常我们约定,两个下划线开头的属性是私有的,其他为公共的
②类内部可以访问私有属性(方法)
③类外部不能直接访问私有属性(方法)
④类外部可以通过“__类名__私有属性(方法)名”访问
class Employee:
def __init__(self,name,age):
self.name = name
self.__age = age
def __work(self):
print("好好工作")
print("年龄:{}".format(self.__age)) #类的内部可以调用
e = Employee("wyj",22)
print(e.name)
print(e._Employee__age)
e._Employee__work()
运行结果为:
wyj
22
好好工作
年龄:22
@property装饰器
可以将一个方法的调用变成“属性调用”
class Employee:
@property
def salary(self):
print("salary runs ...")
return 10000
emp1 = Employee()
print(emp1.salary) #就像引用对象的一个元素
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<50000:
self.__salary = salary
else:
print("录入错误!")
emp1 = Employee("wyj",10000)
print(emp1.get_salary())
emp1.set_salary(2000)
print(emp1.get_salary())
运行结果为:
10000
2000
用@property实现
class Employee:
def __init__(self,name,salary):
self.__name = name
self.__salary = salary #设置私有属性,使在类外部不能修改
@property
def salary(self):
return self.__salary
@salary.setter #针对salary属性的设定
def salary(self,salary):
if 1000<salary<50000:
self.__salary = salary
else:
print("录入错误!")
emp1 = Employee("wyj",10000)
print(emp1.salary)
emp1.salary = 20000
print(emp1.salary)
运行结果为:
10000
20000
面向对象三大特征
三大特征简介
1、封装(隐藏)
①隐藏对象的属性和实现细节,只对外暴露“相关调用方法”
②通过“私有属性、私有方法”实现“封装”,没有严格的语法级别的“访问控制符”,更多依靠程序员自觉实现
2、继承
①继承可以让子类具有父类的特性,提高了代码的重用性
②从设计上是一种增量进化,原有父类设计不变的情况下,可以增加新的功能,或改进已有算法
3、多态
多态是指同一个方法的调用由于对象不同会产生不同的行为
继承
1、是实现代码复用的重要手段
2、语法格式:
class 子类类名(父类1[,父类2...]):
类体
3、如果在类定义中没有指定父类,则默认父类是object类。也就是说,object是所有类的父类,里面定义了一些所有类共有的默认方法,比如:☆__new__()/4、定义子类时,必须在其构造函数中调用父类的构造函数。调用格式如下:
父类名.init(self,参数列表)
class Person:
pass
class Student(Person):
pass
print(Student.mro())
运行结果为:
[<class '__main__.Student'>, <class '__main__.Person'>, <class 'object'>]
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age
def say_hi(self):
print("hi")
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age) #必须显式地调用父类的初始化方法,不然解释器不会调用
self.score = score
s = Student("wyj",22,60)
s.say_hi()
print(s._Person__age)
运行结果为:
hi
22
PS:父类中私有的方法和属性,子类继承了但是不能直接用,可以通过“__类名__私有属性(方法)名”访问
方法的重写
1、成员继承:子类继承了父类除构造方法之外的所有成员
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("我的名字是{}".format(self.name))
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age) #必须显式地调用父类的初始化方法,不然解释器不会调用
self.score = score
def say_introduce(self): #重写了父类的方法
print("报告老师,我的名字是{}".format(self.name))
s = Student("wyj",22,60)
s.say_age()
s.say_introduce()
运行结果为:
我的年龄为: 22
报告老师,我的名字是wyj
查看类的继承层次结构
通过类的方法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'>]
object根类
object类是所有类的父类,因此有必要深入研究一下object类的结构
#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)) #查看object根类的所有属性
s2 = Person("wyj",22)
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']
重写__str__()方法
1、str()是object中的一个方法用于返回一个对于对象的描述
2、对应的内置函数str()经常用于print()方法
class Person:
def __init__(self,name):
self.name = name
def __str__(self):
return "名字是:{}".format(self.name)
p1 = Person("wyj")
print(p1)
运行结果为:
名字是:wyj
多重继承
1、Python支持多重继承,一个子类可以有多个“直接父类”
2、但是这样,类的整体层次会变得复杂,尽量避免使用
class A:
def aa(self):
print("aa")
class B:
def bb(self):
print("bb")
class C(A,B):
def cc(self):
print("cc")
c1 = C()
c1.aa()
c1.bb()
c1.cc()
运行结果为:
aa
bb
cc
mro()
1、通过mro()方法获得“类的层次顺序”
2、解释器的寻找方法是从左向右
class A:
def say(self):
print("aa")
class B:
def say(self):
print("bb")
class C(B,A):
pass
c1 = C()
print(C.mro())
c1.say()
运行结果为:
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
bb
super()获得父类定义
super()代表父类的定义,不是父类对象
class A:
def say(self):
print("A:",self)
class B(A):
def say(self):
super().say() #等同于 A.say()、最终找到的是A类
print("B:",self)
B().say()
运行结果为:
A: <__main__.B object at 0x00000268A5DDADA0>
B <__main__.B object at 0x00000268A5DDADA0>
多态
1、多态是指同一方法调用由于对象不同可能会产生不同的行为
2、多态是方法的多态,属性没有多态
3、多态的存在有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): #注意isinstance()的参数格式
m.eat()
else:
print("不能吃饭")
manEat(Chinese())
manEat(English())
manEat(Indian) #类后边要加括号
运行结果:
筷子
叉子
不能吃饭
特殊方法和运算符重载
Python的运算符实际上是通过调用对象的特殊方法实现的
例如:
a = 20
b = 30
c = a+b #实际上本质是c = a.__add__(b)
重写运算符对应的方法,即实现了“运算符的重载”
class Person:
def __init__(self,name):
self.name = name
def __add__(self,other):
if isinstance(other,Person):
return "{}---{}".format(self.name,other.name)
else:
print("不是同类方法,不能相加")
p1 = Person("wyj")
p2 = Person("JJ")
x = p1+p2
print(x)
运行结果为:
wyj---JJ
特殊属性
Python对象中包含了很多双下划线开始和结束的属性,这些都是特殊属性,有特殊用法
常见的特殊属性:
obj.dict:对象的属性字典
obj.class:对象所属的类
class.bases:类的基类元组(多继承)
class.base:类的基类
class.mro:类的层次结果
class.subclasses():子类列表
对象的浅拷贝与深拷贝
1、变量的赋值操作:只形成两个变量,实际还是指向同一个对象
2、浅拷贝:Python拷贝一般都是浅拷贝;拷贝时,对象包含的子对象内容不拷贝,因此,源对象和拷贝对象会引用同一个子对象
3、深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不同
import copy
class MobilePhone:
def __init__(self,cpu,screen):
self.cpu = cpu
self.screen = screen
class CPU:
def calculate(self):
print("cpu对象:",self)
class Screen:
def show(self):
print("显示")
print("screen对象:",self)
#测试变量赋值
c1 = MobilePhone
c2 = c1 #变量赋值
print(c1)
print(c2) #赋值后二者指向一个对象,地址相同
#测试浅拷贝
s1 = Screen()
m1 = MobilePhone(c1,s1)
m2 = copy.copy(m1)
print(m1,m1.cpu,m1.screen)
print(m2,m2.cpu,m2.screen) #手机不同,其中的cpu和screen是一样的
#测试深拷贝
m3 = copy.deepcopy(m1)
print(m1,m1.cpu,m1.screen)
print(m3,m3.cpu,m3.screen) #手机、cpu、screen都不一样
运行结果为:
<class '__main__.MobilePhone'>
<class '__main__.MobilePhone'>
<__main__.MobilePhone object at 0x000001D2F614B1D0> <class '__main__.MobilePhone'> <__main__.Screen object at 0x000001D2F32E7898>
<__main__.MobilePhone object at 0x000001D2F614B400> <class '__main__.MobilePhone'> <__main__.Screen object at 0x000001D2F32E7898>
<__main__.MobilePhone object at 0x000001D2F614B1D0> <class '__main__.MobilePhone'> <__main__.Screen object at 0x000001D2F32E7898>
<__main__.MobilePhone object at 0x000001D2F614B358> <class '__main__.MobilePhone'> <__main__.Screen object at 0x000001D2F614B2E8>
组合
1、组合与继承类似,使用组合也能实现一个类拥有另一个类的方法和属性
2、继承是“is”的关系,例如狗类继承动物类
3、组合是“has”的关系,例如手机拥有CPU
#使用继承实现代码的复用
class A1:
def say_a1(self):
print("a1")
class B1(A1):
pass
b1 = B1()
b1.say_a1()
#使用组合实现代码的复用
class A2:
def say_a2(self):
print("a2")
class B2:
def __init__(self,a):
self.a = a
a2 = A2()
b2 = B2(a2) #B2包含A2
b2.a.say_a2() #调用了A2中的函数
运行结果为:
a1
a2
设计模式_工厂模式
1、设计模式是指在面临某一问题时的固定的做法
2、对于初学者最常用的两个模式是工厂模式和单例模式
3、工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一的管理和控制
class CarFactory:
def create_car(self,brand):
if brand == "奔驰":
return Benz()
elif brand == "宝马":
return BWM()
elif brand == "比亚迪":
return BYD()
else:
return "未知品牌,无法创建"
class Benz:
pass
class BMW:
pass
class BYD:
pass
factory = CarFactory()
c1 = factory.create_car("奔驰")
c2 = factory.create_car("比亚迪")
print(c1)
print(c2)
运行结果为:
<__main__.Benz object at 0x000002651A094CF8>
<__main__.BYD object at 0x000002651B0F57B8>
设计模式_单例模式
1、单例模式的核心作用是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点
2、单例模式只生成一个实例对象,减少了对系统资源的开销
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)
运行结果为:
init...... #只初始化了一次
<__main__.MySingleton object at 0x000001B9B7A6ADD8>
<__main__.MySingleton object at 0x000001B9B7A6ADD8> #两次引用的同一个地址
来源:CSDN
作者:Bro_Jun
链接:https://blog.csdn.net/Bro_Jun/article/details/104826844