1、面向对象的概念
乱七八糟的一堆概念,参考java吧。
2、定义类
class关键字 类名字:驼峰之类 类属性 类方法
创建实例不需要使用new关键字 属性的使用同java,都是使用点句法 方法的时候用同java,都是使用点句法
class Cart():
color='white'
brand='audi'
pailiang=2.4
def carry(self):
print('the car can carry')
def doufeng(self):
print('the car can run happy')
car1=Cart()
print(car1)
print(car1.brand)
print(car1.color)
car1.carry()
car1.doufeng()
3、类的成员
类的成员不能删除 实例的成员能删除,从类构造的成员不能删除,构造后添加的新属性可以删除(属于实例),这一点和JavaScript比较像
class Car():
color='white'
brand='audi'
pailiang=2.4
def carry(self):
print('the car can carry')
def doufeng(self):
print('the car can run happy')
car1=Car()
print(car1.brand)
del car1.brand
car1.name='byd'
print(car1.name)
del car1.name
print(car1.name)
实例方法的增删也是类似的情形
class Car():
color='white'
brand='audi'
pailiang=2.4
def carry(self):
print('the car can carry')
def doufeng(self):
print('the car can run happy')
car1=Car()
print(car1.brand)
def myfun():
print('hello world')
car1.hellofun=myfun
car1.hellofun()
del car1.hellofun
创建对象,并不是吧属性和方法赋值一份给对象,而是对这些属性和方法的应用(但应该是开了新的内存空间的,不然,修改a实例的属性,会影响到b实例的值)
4、类的成员属性的操作(类似java的静态属性和静态方法)
修改了类属性,再实例化时,实例化对象则引用的是最新的值 类似于修改java的静态类属性,再实例化,以新的值进行实例化
class Car():
color='white'
brand='audi'
pailiang=2.4
def carry(self):
print('the car can carry')
def doufeng(self):
print('the car can run happy')
print(Car.color)
Car.color='black'
print(Car.color)
car1=Car()
print(car1.color)
class Car():
color='white'
brand='audi'
pailiang=2.4
def carry(self):
print('the car can carry')
def doufeng(self):
print('the car can run happy')
Car.name='xiaodi'
print(Car.name)
car1=Car()
print(Car.name)
class Car():
color='white'
brand='audi'
pailiang=2.4
def carry(self):
print('the car can carry')
def doufeng(self):
print('the car can run happy')
Car.name='xiaodi'
print(Car.name)
car1=Car()
print(Car.name)
del Car.color
- 总结:
对象操作成员属性: 访问:通过对象.属性名 修改:通过对象.属性名=新值 添加:通过对象.新属性名=值 删除:del 对象.属性(只能删除对象自己的属性,不能删除类属性)
对象操作成员方法: 访问:通过对象.成员方法名() 修改:通过对象.成员方法名=func 添加:通过对象.方法名=func 删除:del 对象.成员方法名
类操作成员(不推荐) 访问:通过类名.属性名 修改:通过类名.属性名=新值 添加:通过类名.新属性名=值 删除:del 类名.属性(只能删除对象自己的属性,不能删除类属性)
5、self详解
- self是方法中的一个形参,不是关键字
- self在方法中的代码是当前这个对象自己
- self在方法中代表对象可以去操作成员,可以使用self在类的内部访问成员
类似于this关键字
- self在类方法中,代表当前这个对象(同于一般语言的this关键字)
- self代表调用这个方法的对象
- self 可以在类的内部代替对象进行各种操作,只要对象能干的事,self都可以代表对象去做
- 如果定义方法的时候没有使用self参数,在会把对象自己放在参数的位置。所以ide在定义方法的时候,自动把self添加到形参的位置。
- 类在定义时方法是没有使用self形参,定义时不报错(实际报错),但是在使用实例的时候会报错(报错报在定义时,正常不报)。但使用类方法调用的时候不会出现报错
class Person():
name='zhangsan'
age=34
gender='female'
def sing(self):
print('i am singing')
def dance(self):
print('i can dance')
def rap(self):
print('i can rap')
def func(self):
print(self)
print(self.name)
self.high=175
self.rap()
def func2():
print('我在定义时没有使用形参,定义时不报错,但是在使用实例的时候会报错')
p1=Person()
print(p1.name)
print(p1)
p1.func()
p1.name='lisi'
p1.func()
print(p1.high)
p1.func2()
Person.func2()
方法的分类: 非绑定类方法:含有self或者可以接受对象作为参数的方法,可以使用对象或类去方法 绑定类方法:不含self或者不能接受对象最为参数的方法,只能使用类来访问(多少有点java静态方法的意思)
6、初始化方法__init__
魔术方法:
- 和普通方法一样都是类中定义的成员方法
- 不需要手动调用,魔术方法会在某种情况下,自动触发
- 使用两个连续下划线
- 不是自己定义,系统定义好的,我们使用即可
__init__初始化方法
- 在通过类实例化对象后,自动触发的一个方法(实际就是构造方法)
- 在对象实例化后完成对象的初始化
class Person():
name=None
age=None
gender=None
def __init__(self,name,age,gender):
self.name=name
self.age=age
self.gender=gender
print('i am init method')
def say(self):
print('i will introduce myself to u')
p1=Person('lisi',33,'female')
print(p1.name)
p1.say()
7、析构方法__del__
__del__析构方法
- 当前类实例化的对象被销毁时,自动触发
- 可以在析构方法中完成一些特殊任务,如在初始化中打开的文件,在析构是关闭
import time
class WriteLog():
fileurl='./'
filename='dalta2021.txt'
def __init__(self):
self.fileobj=open(self.fileurl+self.filename,'a+',encoding='utf-8')
def log(self,str):
print(f'把{str}写入文件中')
def __del__(self):
print('析构方法被触发了')
self.fileobj.close()
mylog=WriteLog()
mylog.log('被写入的文本')
析构方法作用的场景
- 程序执行完毕,内存所有资源都会被销毁释放
- 使用del手动删除
- 对象不再被引用时,会自动销毁
8、三大特性–封装
访问级别 public _:一个下划线是protected __:两个下划线是private
- 在python中给成员进行私有化,其实就是改了成员的名字,实际上相相当于_类名__成员名
__dict__获取所有成员属性 dir())获取所有成员属性及方法
- 外部可以访问受保护(protected)成员,因为ptyhon实际上没有受保护成员一说,没有实现受保护
- 外部不能访问私有成员
class Person():
name=None
_age=None
__gender=None
def __init__(self,name,age,gender):
self.name=name
self._age=age
self.__gender=gender
def _say(self):
print('talk somthing')
def __sing(self):
print('sing a song')
p1=Person('zhangsan',34,'female')
print(p1.__dict__)
print(p1.__dir__())
print(p1._age)
p1._say()
print(p1._Person__gender)
9、三大特性–继承
父类:基类,超类 子类:派生类 在于提升代码的重用性 建立新的类与类的关系
继承的特征
- 在不指定继承的父类时,所有类都继承自object类
- 子类继承父类后,拥有了弗雷中的所有成员包括魔术方法(私有成员除外)
- 子类继承父类后,并不会把父类的成员复制给子类,而是应用
- 子类继承父类后可以重写父类方法
- 子类重写父类的方法,依然可以使用super().父类方法名()的方式调用
- 子类可以扩展父类方法
继承的语法格式
class father():
pass
class son(father):
pass
- 继承后可以重写,扩展父类方法
- 子类也可以使用super().父类方法名 来直接调用父类方法
- 父类方法如有参数,子类直接调用是也应当带参
class Moke():
color='baowen'
gender='male'
def run(self):
print('runing')
def crawl(self):
print('paing')
class Cat(Moke):
name='miaomiao'
def say(self):
print('miao miao miao')
def crawl(self):
print('miao papapa')
def play(self):
super().crawl()
print('调用了父类方法')
c1=Cat()
print(c1.color)
print(c1.name)
c1.run()
c1.say()
c1.crawl()
c1.play()
10、三大特性–多继承
一个类继承多个父类(java只能单继承) 一个类也可以链式继承(祖传的继承)
语法格式:
class father():
pass
class mother():
pass
class son(father,mother):
pass
案例
class Father():
def eat(self):
print('风卷残云')
def batter(self):
print('battle as a man')
class Mother():
def eat(self):
print('浅尝辄止')
def dance(self):
print('dance as a girl')
class Son(Father,Mother):
def eat(self):
super().eat()
print('好吃的风卷残云,不好吃的浅尝辄止')
s1=Son()
s1.eat()
s1.batter()
s1.dance()
11、三大特性–菱形继承
B,C继承A D继承B,C 结果就是一个菱形继承 继承链条是D==》B==》C==》A
多继承重新定义了类的关系
class Human():
number=444
def eat(self):
print(self.number)
print(self)
print('顿顿都是小烧烤')
class Father(Human):
number = 333
def eat(self):
super().eat()
print(super().number)
print('风卷残云')
def batter(self):
print('battle as a man')
class Mother(Human):
number = 222
def eat(self):
super().eat()
print(super().number)
print('浅尝辄止')
def dance(self):
print('dance as a girl')
class Son(Father,Mother):
number=111
def eat(self):
super().eat()
print(super().number)
print('好吃的风卷残云,不好吃的浅尝辄止')
c1=Son()
c1.eat()
结果是:
111
<__main__.Son object at 0x00000157069AB790>
顿顿都是小烧烤
444
浅尝辄止
222
风卷残云
333
好吃的风卷残云,不好吃的浅尝辄止
super():使用super去调用父级的方法时,实际上是在用super调用mro列表中的上一级方法(mro()返回所有的继承链) super()本身调用父级方法时,传递的self对象,就是这个方法中的self对象(第一层的self)自己
12、三大特性–继承关系检测
实现继承后,程序会自动生成一个继承列表MRO(method relation Order)方法关系列表 MRO列表生成原则
- 子类永远在父类前面
- 同一登记的类,按照子类中的继承顺序摆放
- 先子类,后父类的顺序原则,最终是object类
- super()在调用时,并不是查找父类,而是去mro列表还早上一个类
- super()方法在调用时,会自动吧当前self插入到上一级的类方法中
**issubclass()**子类检测
class Father():
def eat(self):
print('风卷残云')
def batter(self):
print('battle as a man')
class Son(Father):
def eat(self):
print('好吃的风卷残云,不好吃的浅尝辄止')
c1=Son()
c1.eat()
print(Son.mro())
res=issubclass(Son,Father)
print(res)
13、三大特性–多态
对与同一个方法,由于调用的对象不同,产生了不同心态的结果
class Computer():
def usb(self,obj):
obj.start()
class Mouse():
def start(self):
print('mouse is start,u can click or double click')
class Keyboard():
def start(self):
print('keyboard is start , u can type somthing')
class UsbDisk():
def start(self):
print('udisk is insert , u can store files')
c1=Computer()
m1=Mouse()
k1=Keyboard()
u1=UsbDisk()
c1.usb(m1)
c1.usb(k1)
c1.usb(u1)
14、三大特性–多态-继承
- 定义一个接口规范类,其他类都继承这个类,并实现(重写)父类中的方法
- 由于每个对象实现父类方法的方式或者过程都不相同,最后的结果是不一样的心态
- 类似于java的接口(interface)
以下代码体现出一种接口规范
class Usb():
def start(self):
pass
class Mouse(Usb):
def start(self):
print('mouse is start,u can click or double click')
class Keyboard(Usb):
def start(self):
print('keyboard is start , u can type somthing')
class UsbDisk(Usb):
def start(self):
print('udisk is insert , u can store files')
m1=Mouse()
k1=Keyboard()
u1=UsbDisk()
m1.start()
k1.start()
u1.start()
|