方法签名包含 3个部分:方法名、参数数量、参数类型。
python 中,类体方法的的参数没有声明类型(调用时确定参数的类型),参数的数量也可以由可变参数控制。如果我们在类体中定义了多个重名的方法,只有最后一个方法有效。
#测试python中重命名方法
class mytype():
def say_hi(self,name):
print('你好')
def say_hi(self,name):
print('{0}你好呀'.format(name))
p1=mytype()
p1.say_hi('孙悟空')
建议:不要使用重名的方法!Python 中方法没有重载。
Python 是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有的方法。
#方法的动态性
class Mytype:
def work(self):
print('好好学习')
def play(s):
print('{0}玩游戏'.format(s))
def work1(s):
print('你好')
P=Mytype()
Mytype.work= work1
Mytype.play=play
P.work()
P.play()
Python 对于类的成员没有严格的访问控制限制,这与其他面向对象语言有区别。关于私有
属性和私有方法,有如下要点:
(1). 通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。
(2). 类内部可以访问私有属性(方法)
(3). 类外部不能直接访问私有属性(方法)
(4). 类外部可以通过“_类名__私有属性(方法)名”访问私有属性(方法)
#私有属性和方法的测试
class Sea:
__Area=10000
def __init__(self,name,volume):
self.name=name
self.__volume=volume
def say_Sea(self):
print("海洋的面积是{0}".format(Sea.__Area))
print("{0}的体积是{1}".format(self.name,self.__volume))
P1=Sea('太平洋',1200)
print(P1.name)
print(dir(P1))
P1.say_Sea()
print(P1._Sea__volume) #**注意格式问题Sea后无右下角的点**
property即是属性的意思
@property 可以将一个方法的调用方式变成“属性调用”。
装饰器的使用方法
#property装饰器的使用
class employee:
@property
def say_salary(self):
print('夏明的薪资很多')
return 1000
P1=employee()
#P1.say_salary()
print(P1.say_salary)
打印薪资
#property的使用方法
class employee:
def __init__(self,name,salary):
self.__name=name
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('录入错误,请重新输入')
P1=employee('悟空',10000)
P1.salary=-3000
P1.salary=3000
print(P1.salary)
P1.salary=4000
print(P1.salary)
(1). 类名首字母大写,多个单词之间采用驼峰原则。
(2). 实例名、模块名采用小写,多个单词之间采用下划线隔开。
(3). 每个类,应紧跟“文档字符串”,说明这个类的作用。
(4). 可以用空行组织代码,但不能滥用。在类中,使用一个空行隔开方法;模块中,使用两个空行隔开多个类。
(1)封装(隐藏);(2)继承; (3)多态
如果一个新类继承自一个设计好的类,就直接具备了已有类的特征,就大大降低了工作难度。已有的类,我们称为“父类或者基类”,新的类,我们称为“子类或者派生类”。
Python 支持多重继承,一个子类可以继承多个父类。
#继承的方法测试
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def say_age(self):
print(self.name,'的年龄是',self.age)
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age)
self.score=score
s=Student('悟空',80,30)
s.say_age()
print(s.name)
print(Person.mro())
print(Student.mro())
(1). 成员继承:子类继承了父类除构造方法之外的所有成员。
(2). 方法重写:子类可以重新定义父类中的方法,这样就会覆盖父类的方法,也称为“重写”.
#继承和方法重写
class Person:
def __init__(self,name,age):
self.name=name
self.age=age
def say_age(self):
print(self.name,'的年龄是',self.age)
def say_name(self):
print('我的名字是{0}'.format(self.name))
class Student(Person):
def __init__(self,name,age,score):
Person.__init__(self,name,age)
self.score=score
def say_name(self):
print('大家好,我的名字是{0}'.format(self.name))
s=Student('悟空',80,30)
s.say_age()
s.say_name()
通过类的方法 mro()或者类的属性__mro__可以输出这个类的继承层次结构。
#类的层次结构
class A:
pass
class B(A):
pass
class C(B):
pass
print(C.mro())
内置函数 dir(),它可以方便的看到指定对象所有的属性。
object 有一个__str__()方法,用于返回一个对于“对象的描述”,对应于内置函数 str(),经常用于 print()方法,帮助我们查看对象的信息。str()可以重写。
#__str__()
class Person:
def __init__(self,name):
self.name=name
def __str__(self):
return '我的的名字是{0}'.format(self.name)
s=Person('悟空')
print(s)
print(dir(s))
Python 支持多重继承,一个子类可以有多个“直接父类”。这样,就具备了“多个父类”的特点。但是由于,这样会被“类的整体层次”搞的异常复杂,尽量避免使用。
Python 支持多继承,如果父类中有相同名字的方法,在子类没有指定父类名时,解释器将**“从左向右”**按顺序搜索。
在子类中,如果想要获得父类的方法时,我们可以通过 super()来做,super()代表父类的定义,不是父类对象。
#super()方法的使用
class A:
def say_a(self):
print('你好,悟空')
print('你好,八戒')
class B(A):
def say_b(self):
super().say_a() #调用父类A中的方法
print('你好,悟净')
s=B()
s.say_b() #此时A中的方法也会被调用
多态(polymorphism)是指同一个方法调用由于对象不同可能会产生不同的行为。关于多态要注意以下 2 点:
(1). 多态是方法的多态,属性没有多态。
(2). 多态的存在有 2 个必要条件:继承、方法重写。
#多态的使用
class Animal:
def shout(self):
print('动物叫了一声')
class Cat(Animal):
def shout(self):
print('小猫喵喵')
class Dog(Animal):
def shout(self):
print("小狗汪汪")
class Fly:
def shout(self):
print("苍蝇嗡嗡")
def Animalshout(a):
if isinstance(a,Animal):
a.shout()
else:
print('乱吼一通')
Animalshout(Dog())
Animalshout(Cat())
Animalshout(Fly())
Python 的运算符实际上是通过调用对象的特殊方法实现的
#运算符的重载
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:
print('不是同类对象不能相加')
def __mul__(self, other):
if isinstance(other, int):
return self.name * other
else:
return "不是同类对象, 不能相乘"
x1=Person('悟空')
x2=Person('八戒')
x3=Person('悟净')
y=x2+x3
s=x1+x2
print(s)
print(y)
print(x1*4)
Python 对象中包含了很多双下划线开始和结束的属性,这些是特殊属性,有特殊用法。
#测试特殊属性
class A:
pass
class B:
pass
class C(B,A):
def __init__(self,nn):
self.nn = nn
def cc(self):
print("cc")
c = C(3)
print(dir(c)) #查看对象属性
print(c.__dict__) # 对象的属性字典
print(c.__class__) # 对象属性的类
print(C.__bases__) # 类的基类元组(多重继承)
print(C.__base__) #类的基类
print(C.mro()) # 类的层次结构
print(A.__subclasses__()) #子类列表
只是形成两个变量,实际还是指向同一个对象。
Python 拷贝一般都是浅拷贝。拷贝时,对象包含的子对象内容不拷贝。因此,源对象和拷贝对象会引用同一个子对象。
使用 copy 模块的 deepcopy 函数,递归拷贝对象中包含的子对象。源对象和拷贝对象所有的子对象也不同
#测试深拷贝和浅拷贝
import copy
class MobilePhone:
def __init__(self,cpu,screen):
self.cpu=cpu
self.screen=screen
class CPU:
def show_CPU(self):
print('CPU是核心处理器')
class Screen:
def show_Screen(self):
print('Screen是显示器')
#测试变量赋值
c=CPU()
c1=c
print(c1)
print(c)
#测试浅复制
print('测试浅复制')
s=Screen()
m1=MobilePhone(s,c)
m2=copy.copy(m1)
print(m1,m2)
print(m1.screen,m2.screen)
#测试深复制
print('测试深复制')
m3=copy.deepcopy(m1)
print(m1,m3)
print(m1.screen,m3.screen)
“is-a”关系,我们可以使用“继承”。从而实现子类拥有的父类的方法和属性。“is-a”
关系指的是类似这样的关系:狗是动物,dog is animal。狗类就应该继承动物类。
“has-a”关系,我们可以使用“组合”,也能实现一个类拥有另一个类的方法和属性。”
has-a”关系指的是这样的关系:手机拥有 CPU。 MobilePhone has a CPU。
#测试继承
class MobilePhone:
def say_Phone1(self):
print('手机拥有处理器')
def say_Phone2(self):
print('手机拥有显示器')
class CPU(MobilePhone):
pass
c=CPU()
c.say_Phone1()
#测试组合
class Screen:
def __init__(self, a):
self.a = a
m=MobilePhone()
s=Screen(m)
s.a.say_Phone2
对于初学者,学习两个最常用的模式:工厂模式和单例模式
工厂模式实现了创建者和调用者的分离,使用专门的工厂类将选择实现类、创建对象进行统一的管理和控制。
单例模式(Singleton Pattern)的核心作用是确保一个类只有一个实例,并且提供一个访问该实例的全局访问点。