最近准备HCIE的考试,用空余时间高强度学习python
介绍了Python中面向对象编程的基本概念,包括类、类的属性、类的方法、类的方法中实例方法、类方法、静态方法,在类与对象中动态添加属性和方法,以及继承、类变量、多态等概念
类(类对象):为了做区分而创建的一些特性的群体
子类:通过继承创建,为了在类下做更清晰的区分
对象:建立在类的基础上,在某一类或子类下的个体
实例:约等于对象,xx对象是xx类的实例化
在python中,一切都是对象;凡是对象,都是某个类的实例
使用面向对象编程,在做好细分之后,能够更快实现功能,更容易维护 类越细分,对象就越精细
类1 → 对象1,对象2
↓
子类1 → 对象1,对象2
子类2...
子类3...
面向对象有三大特征:封装、继承、多态
#创建类————使用class关键字
#class 类名() 括号代表要继承,在规范上,类名的首字母要大写
class Ws:
pass
class Xhy:
pass
#创建对象——根据类创建一个属于这个类的对象
v1 = Ws() #v1是由Ws这个类实例化生成的对象,v1这个对象是Ws类的实例
v2 = Ws()
v3 = Ws()
#类————管理员、用户
#类的属性————是类里的变量。反映该类对象的信息,例如账号、密码、名字等
#类的方法————是类里的函数。反映该类对象能做的事,例如账号权限、添加用户、修改密码等,是一种方法,比如list.append,是自己定义的函数
#添加类的属性,一般都是类的可变属性
#添加一个不变的属性
class User_info: #通过__init__构造方法
def __init__(self): #self代表要被实例化的对象
self.username = 'ws' #为其赋值
self.age = '24'
self.password = 'ws111'
user1 = User_info()
print(user1.password)
#ws111
#添加类的可变属性,这样可以适用更多user
class User_info:
def __init__(self,username,age,password):
self.username = username
self.age = age
self.password = password
user1 = User_info('ws',24,'ws111')
user2 = User_info('xhy',23,'xhy111')
print(user1.username)
print(user2.password)
#ws
#xhy111
#添加类的方法,在创建了对象之后,就可以直接使用类的方法
class User_info:
def __init__(self,name,password,age):
self.name = name
self.password = password
self.age = age
def show(self):
print(self.name, self.password)
def show_age(self):
print(self.age)
user1 = User_info('ws','ws111',age=24)
user1.show()
#ws ws111
user1.show_age()
#24
#在方法中定义的类的属性,可以在全局进行调用
class User_info:
def __init__(self,name):
self.name = name
def show_age(self):
self.age = 24 ####在方法中定义类的属性
print(self.age)
user1.show_age()
#24
#实例方法————首个参数为self的方法,绑定给该类的实例调用,类本身不能调用
class User_info:
def __init__(self,name):
self.name = name
def show(self):
pass
user1 = User_info('ws') #在实例方法中,必须要创建一个实例,才能使用类中的方法
user1.show()
#无法用类来直接调用,像User_info.show这样的用法
#类方法————首个参数为cls,并且以classmethod装饰的方法
#可以直接使用类来调用如User_info.show,但无法调用类的参数
class User_info:
def __init__(self,name):
self.name = name
@classmethod
def show(cls):
print('ws')
@classmethod
def show_name(cls):
print(self.name)
User_info.show()
#ws
User_info.show_name()
#报错,无法调用类的参数
#如果需要则需要额外在类方法中传入参数
class User_info:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod #类方法的装饰器
def show_name(cls, age):
print(age)
User_info.show_name(24)
#24
#静态方法————不需要cls或self,使用staticmethod装饰,可以直接调用,但无法使用类的属性
class User_info:
def __init__(self, name):
self.name = name
@staticmethod
def show_name(): #需要传参则定义形参
print('11111')
User_info.show_name()
#11111
动态添加属性、修改属性
#动态的添加对象和类的属性
# 添加到对象只会影响对象本身,而为类添加的属性会应用给所有对象
class User_info:
def __init__(self, name):
self.name = name
self.username = 'ws' #添加一个固定的类的属性值
if __name__ == '__main__':
user1 = User_info('ws') #创建了一个实例/对象user1
user1.age = 24 #age这个属性只属于user1这个对象中,而不属于User_info的类
print(user1.age)
#24
user1.age = 25 #动态修改对象的属性值
print(user1.age)
# 25
User_info.password = 'ws111' #为类添加属性,如果没有会添加到user1中,且值是可修改
print(user1.password)
#ws111
User_info.password = 'xhy111' #为类添加属性,如果原本有值就会修改
print(user1.password)
#xhy111
User_info.username= 'xhy' #无法动态修改类中原本就有的属性值,实例化后的对象继承了类的值,不会变化
print(user1.username)
#ws
动态添加方法
添加实例方法、添加类方法、添加静态方法
#添加实例方法————只能单独为对象添加,不能为类添加
import types #导入types模块
class User_info:
pass
def show(self): #准备一个实例方法
print('111')
if __name__ == '__main__':
user1 = User_info() #实例化一个对象
#目标实例的方法 = types.MethodType(待添加函数名,目标函数名)
user1.show = types.MethodType(show,user1)
user1.show()
#111
#添加类方法———只能为类添加
class User_info:
pass
@classmethod
def show(cls):
print('111')
if __name__ == '__main__':
User_info.show = show #直接赋值就行,不要调用
User_info.show()
#111
#添加静态方法————只能为类添加
class User_info:
pass
@staticmethod
def show():
print('111')
if __name__ == '__main__':
User_info.show = show
User_info.show()
#111
子类继承父类之后可以直接使用父类定义好的属性和方法
#最简单的继承性质说明
class User():
def __init__(self,name):
self.name = name
def show(self):
print('111')
#class 子类名(父类名)
class U001(User):
def age(self): #可以在子类里定义新的方法,只属于这个子类可用的
print('123')
def show(self): #可以在子类里重写父类的方法,会盖掉父类的方法
print('222')
if __name__ == '__main__':
user1 = U001('ws')
user1.show()
#222
#super函数————调用父类的 方法
#继承父类方法————可以在子类的方法中调用父类的任意方法
class User:
def __init__(self):
self.age = 24
def show(self,name):
print(f'{self.age}岁,{name},是学生') #调用age
class U01(User):
def __init__(self):
self.age = 26
def show2(self):
print('222') #多加一行显示区别
super().show('ws') #调用了父类中的方法show,并且原函数需要传参,所以这里也传参
if __name__ == '__main__':
user1 = U01()
user1.show2() #调用的类的属性26岁是本类的属性,而不是父类的属性24岁
#222
#26岁,ws,是学生
#继承父类属性————分多种情况
1、全部保留属性,不新增
2、全部替换,只用自己的
3、保留部分属性,不新增
4、保留部分属性,有新增
#全部保留属性,不新增
class User_info:
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
class User(User_info):
pass #最简单,直接什么都不用动,不重写则全部保留
if __name__ == '__main__':
user1 = User('ws','ws111','1320')
print(user1.username)
#ws
#全部替换,只用自己的
class User_info:
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
class User(User_info):
def __init__(self,age,job): #重写构造函数
self.age = age
self.job = job
if __name__ == '__main__':
user1 = User('ws','ws111')
print(user1.age)
#ws
print(user1.username)
# 报错
#保留部分属性,不新增
class User_info:
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
class User(User_info):
def __init__(self,username,password):
# 使用super,重跑一遍父类构造函数的形参,并且只赋值自己要的,不要的空着
super().__init__(username=username,password=password,email=None)
#这样就只传了name和password两个属性
if __name__ == '__main__':
user1 = User('ws','ws111')
print(user1.username)
#ws
#保留部分属性,有新增
class User_info:
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
class User(User_info):
def __init__(self,username,password,job):
self.job = job #新增一个job属性
super().__init__(username=username,password=password,email=None)
if __name__ == '__main__':
user1 = User('ws','ws111','student')
print(user1.username,user1.job)
#ws student
在类中设置的变量,但不是类的属性
先介绍python中使用的查找算法
#Python的查找算法(包括变量的查找、类变量的查找、super函数调用)
#原则是自下而上,从里到外
#变量的查找
def fun():
v1 = 0
def fun1():
v1 = 1 #先找最里层,即fun1中的v1
print(v1)
if __name__ == '__main__':
v1 = 2
fun()
#1
#super函数的调用
class fun:
def show(self):
pass
class fun1(fun):
pass
class fun2(fun1)
def show2(self):
super().show() #这条super的对函数的调用首先会在fun1中寻找,然后去fun中寻找
if __name__ == '__main__':
pass
#mro查找算法——应对多继承的情况下的查找
#应用于一个类继承了多个类的情况
#mro采用的算制为C3,融合了DFS(深度查询)和BFS(广度查询)
class fun():
pass
class fun1():
pass
class fun2(fun,fun1):
pass
if __name__ == '__main__':
v1 = fun2()
print(v1.var) #DFS按顺序,首先查找fun以及fun的父类,再查询fun1以及fun1的父类
#类变量
#类变量可以使用类来访问和修改
class User_info():
v1 = 0
def __init__(self,name):
self.name = name
if __name__ == '__main__':
user1 = User_info('ws')
User_info.v1 = 1 #只使用类来访问和修改
print(User_info.v1)
#1
#如果user1中没有v1的变量,则去user1的父类User_info中找v1
print(user1.v1)
#1
user1.v1 = 2 #为对象动态添加了一个属性
print(user1.v1) #优先使用user1的v1
#2
print(User_info.v1)
#1
用来控制对象的行为
不同的对象调用同一个方法,表现出不同的状态
#多态需要有继承,只发生在父类和子类之间,需要有重写
#仅需一个函数,传递不同的对象,就能使用不同子类中的制定函数
#可扩展性和可维护性都增加了
class Version:
def what(self):
print('Version')
class V1(Version):
def what(self):
print('v1')
class V2(Version):
def what(self):
print('v2')
class V3(Version):
def what(self):
print('v3')
def fun(object):
object.what()
if __name__ == '__main__':
v1 = V1()
v2 = V2()
v3 = V3()
fun(v1)
fun(v2)
fun(v3)
#v1
#v2
#v3