python基础
面向对象
类和对象
类是对一系列具有相同特征和行为的事物的统称,是一个抽象概念,并不是真实存在的事物。
类和对象的关系:使用类来创建对象,对象是类的实例
对象名=类名()
定义类的语法:
class 类名:
属性
方法
类名的命名需要遵守大驼峰命名规则
self
代指调用该函数的对象,直接打印self得到的是该对象的内存地址跟打印对象得到的结果是一样的
添加和获取对象属性
在调用时添加
对象.属性=值
在调用时获取
对象.属性
在类里面添加
self.属性=值
在类里面获取
self.属性
魔法方法
xx这种类型的方法称为魔法方法,指的是具有特殊功能的函数
在另一篇博客中会有所有魔法方法的详细介绍以及对应用途【python进阶——魔法方法】https://www.jianshu.com/p/d5e84f4fdef9
继承
继承是在类定义时将要继承的父类写在括号中,如果有多个父类则按顺序继承
如果没有显示要继承的父类,默认继承object。object默认为所有类的父类。object类是顶级类或基类;其他⼦类叫做派⽣类。
子类默认继承父类的所有方法和属性,但不包括私有方法和属性
单继承
子类可以继承父类的非私有属性和方法,如果子类有同名属性和方法则为重写父类的属性和方法。程序调用时会优先去子类里找,如果子类没有则会去父类中找
如果子类没有重写父类的魔法方法,则会默认使用父类的
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是父类的方法,self为调用对象的,所以谁调用传的是谁的属性,如果子类没有该属性,则传递的还是父类的属性【%s,%s】'%(self.name,self.small))
def __xifu(self):
print('我老婆叫可可')
class Sun(Father):
pass
调用部分:
from clas_20210711.继承 import Father,Sun
if __name__ == '__main__':
zhangsan = Father('zhangsan',45,1000000)
xiaoming = Sun('小明',25,10000)。# 使用了父类的初始化方法
xiaoming.study() # 我是父类的方法,self为调用对象的,所以谁调用传的是谁的属性,如果子类没有该属性,则传递的还是父类的属性【小明,这是可以继承的属性】
print(xiaoming.small) # 这是可以继承的属性
多继承
多继承就是一个类同时继承了多个类,所以这个类可以同时拥有多个父类的非私有属性和方法。但是如果在没有重写的情况下,父类的方法或者属性重名了,则默认使用第一个父类的属性和方法
程序在调用时会首先去子类中找,子类中没有再去第一个父类中找,若没有按顺序往后找,直到找到,若找不到则报错
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是父类的方法,self为调用对象的,所以谁调用传的是谁的属性,如果子类没有该属性,则传递的还是父类的属性【%s,%s】'%(self.name,self.small))
def sleep(self):
print('我是Father类的方法')
def __xifu(self):
print('我老婆叫可可')
def __str__(self):
return '我是父类'
class Study:
price = 5000
def study(self):
print('我是Study类的方法')
class Sun(Study,Father):
pass
调用部分:
from clas_20210711.继承 import Father,Sun
if __name__ == '__main__':
xiaoming = Sun('小明',25,10000)
'''两个类中都有的'''
xiaoming.study() # 我是Study类的方法
'''只有father类中有的'''
xiaoming.sleep() # 我是Father类的方法
'''只有school类中有的'''
print(xiaoming.price) # 5000
重写
上面说到子类默认继承父类的属性和方法,如果子类中有父类的同名方法和属性,则为重写。重写后调用方法和属性时执行的是子类的
super
如果要在子类的方法中调用父类的方法可以使用父类类名.方法名来调用。但是这样如果后面修改了父类的名字,需要手动在子类调用父类方法的地方将名字改掉。所以super出现的意义就是在这种情况下可以兼容这种修改操作。
super(子类名,selt)等价于父类名,然后再调用父类的方法即可
如果是多继承,遵循mro的调用顺序。super适合单继承中使用
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是父类的方法,self为调用对象的,所以谁调用传的是谁的属性,如果子类没有该属性,则传递的还是父类的属性【%s,%s】'%(self.name,self.small))
def sleep(self):
print('我是Father类的方法')
def __xifu(self):
print('我老婆叫可可')
def __str__(self):
return '我是父类'
class Study:
price = 5000
def study(self):
print('我是Study类的方法')
class Sun(Study,Father):
def study(self):
super(Sun, self).study()
print('我是子类的study方法')
类调用部分:
from clas_20210711.继承 import Father,Sun
if __name__ == '__main__':
xiaoming = Sun('小明',25,10000)
# '''两个类中都有的'''
xiaoming.study()
'''
我是Study类的方法
我是子类的study方法
封装
私有属性和方法
设置私有属性喝方法只需要在属性名或者方法名前面加两个下划线__
私有属性和私有方法只能在类里面访问和修改
将私有属性和方法通过包装成非私有方法的形式实现调用和赋值的过程称为封装
通过封装我们可以控制对私有属性的控制和修改权限,提高数据的安全性
封装的get、set方法的命名规则为get_属性名、set_属性名
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是父类的方法,self为调用对象的,所以谁调用传的是谁的属性,如果子类没有该属性,则传递的还是父类的属性【%s,%s】'%(self.name,self.small))
def sleep(self):
print('我是Father类的方法')
def __xifu(self):
print('我老婆叫可可')
def __str__(self):
return '我是父类'
def get_done(self):
return self.__dono
def set_done(self,dono):
self.__dono = dono
调用部分:
from clas_20210711.继承 import Father,Sun
if __name__ == '__main__':
zhangsan = Father('zhangsan',45,50000)
print(zhangsan.get_done()) # 这是我自己的
zhangsan.set_done('现在呢')
print(zhangsan.get_done()) # 现在呢
print(zhangsan.__done) # AttributeError: 'Father' object has no attribute '__done'
'''
如果直接对象名.属性名是拿不到属性值的,会报错。所以如果是只想给读权限可以只提供get方法,只写权限只提供set方法来达到控制权限的目的
'''
多态
用一句话说就是传入同一个对象,产生不同的结果
多态是通过继承来实现的,多个子类继承同一个父类,并重写父类的方法。调用者传入不同子类对象得到不同的实现方法
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是老爹的study方法')
def __str__(self):
return '我是父类'
def get_done(self):
return self.__dono
def set_done(self,dono):
self.__dono = dono
class Sun2(Father):
def study(self):
print('我是老二的study方法')
class Sun(Father):
def study(self):
print('我是老大的study方法')
调用部分:
from clas_20210711.继承 import Father, Sun, Sun2
def stu(father): # 传入不同的对象执行不同的方法
father.study()
if __name__ == '__main__':
zhangsan = Father('zhangsan', 45, 50000)
xiaoming = Sun('小明',20,10000)
xiaogang = Sun2('小刚',21,12000)
stu(xiaogang) # 我是老二的study方法
stu(xiaoming) # 我是老大的study方法
类属性和实例属性
类属性是类定义时声明的属性,需要赋默认值
类属性是为类所拥有的,它可以被该类的所有实例属性共有。如果没有定义同名的实例属性则可以使用类名或者实例名调用,如果定义了同名的实例属性,则实例名调用时优先调用的是实例属性而不是类属性
类属性的优点
如果所有实例都有共同的数据时,可以定义为类属性
实例属性为每个对象单独开辟⼀份内存空间来记录数据,⽽类属性为全类属性实例所共有 ,仅占用⼀份内存,更加节省内存空间。
类方法
可以直接通过类名调用不需要传对象的方法叫做类方法,类里定义的方法默认为实例方法,需要通过装饰器@classmethod来指定其为类方法,需要注意第一个参数必须是类对象,一般定义为cls
一般类方法和类属性一起使用,比如访问类的私有属性
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是老爹的study方法')
@classmethod
def have_done(cls):
return cls.__dono
调用部分:
from clas_20210711.继承 import Father, Sun, Sun2
def stu(father): # 传入不同的对象执行不同的方法
father.study()
if __name__ == '__main__':
print(Father.have_done(Father)) # 如果不写classmethod装饰器需要把类名当参数传入才能调用该方法
print(Father.have_done())
静态方法
静态方法可以不用把self和cls作为参数传入,使用装饰器@staticmethod来指定方法为静态方法
优点为减少不必要的内存占用和性能消耗
静态方法既可以通过类名调用也可以通过实例名调用
例子:
类定义部分:
class Father:
name = 'zhangsan'
age = 20
money = 500000
__dono = '这是我自己的'
small = '这是可以继承的属性'
def __init__(self,name,age,money):
self.name = name
self.age = age
self.money = money
def study(self):
print('我是老爹的study方法')
@classmethod
def have_done(cls):
return cls.__dono
@staticmethod
def sleep(): # 如果没有@staticmethod 不传参编译不通过
调用部分:
from clas_20210711.继承 import Father, Sun, Sun2
def stu(father): # 传入不同的对象执行不同的方法
father.study()
if __name__ == '__main__':
zhangsan = Father('zhangsan', 45, 50000)
zhangsan.sleep() # 睡觉啦
Father.sleep() # 睡觉啦