python 面向对象
面向对象设计(Object oriented design):将一类具体事物的数据和动作整合到一起,即面向对象设计
面向对象编程(object-oriented programming):用定义类+实例/对象的方式去实现面向对象的设计
1. 类和对象
1.什么叫类:类是一种数据结构,就好比一个模型,该模型用来表述一类事物(事物即数据和动作的结合体),用它来生产真实的物体(实例)。
2.什么叫对象:睁开眼,你看到的一切的事物都是一个个的对象,你可以把对象理解为一个具体的事物(事物即数据和动作的结合体)
(铅笔是对象,人是对象,房子是对象,狗是对象,alex是对象,配齐是对象,元昊是对象)
3.类与对象的关系:对象都是由类产生的,上帝造人,上帝首先有一个造人的模板,这个模板即人的类,然后上帝根据类的定义来生产一个个的人
4.什么叫实例化:由类生产对象的过程叫实例化,类实例化的结果就是一个对象,或者叫做一个实例(实例=对象)
类是用来描述一类事物,类的对象指的是这一类事物中的一个个体
是事物就要有属性,属性分为
1:数据属性:就是变量
2:函数属性:就是函数,在面向对象里通常称为方法
注意:类和对象均用点来访问自己的属性
类的函数属性还没有传参数
#注意:类和对象均用点来访问自己的属性
class Chinese:
"这个一个中国人的类"
dang = "***" #类的数据属性:就是变量
def sui_di_tu_tan(): #类的函数属性:就是函数,在面向对象里通常称为方法
print("吐了一口痰")
def cha_dui(self): #函数属性:就是函数,在面向对象里通常称为方法
print("插到了前面")
print(Chinese.dang)
Chinese.sui_di_tu_tan()
Chinese.cha_dui("先随便传一个参数")
print("---------------")
#类名.__dict__:查出的是一个字典,key为属性名,value为属性值
print(Chinese.__dict__["dang"]) # __dict__ 里面存的是Chinese 的属性字典
Chinese.__dict__["sui_di_tu_tan"]() # 可以通过 __dict__ 里面的key调用Chinese的属性
Chinese.__dict__["cha_dui"]("先随便传一个参数")
类和对象
#def __init__(self,name,age,gender): #实例化的过程可以简单理解为执行该函数的过程,实例本身会当作参数传递给self(这是默认的步骤)
class Chinese:
"这个一个中国人的类"
dang = "***" #类的数据属性:就是变量
def __init__(self,name,age,gender): #实例的数据属性
self.mingzi = name
self.nl = age
self.xb = gender
def sui_di_tu_tan(self): #类的函数属性:就是函数,在面向对象里通常称为方法
print("%s %s %s 吐了一口痰"%(self.mingzi,self.nl,self.xb))
def cha_dui(self): #类的函数属性:就是函数,在面向对象里通常称为方法
print("%s 插到了前面"%self.mingzi)
p1 = Chinese("tom",18,"男") #实例化 创建一个对象p1
print(p1.mingzi,p1.nl,p1.xb) #打印实例的数据属性
print(p1.__dict__) # __dict__ 里面存的是p1 的属性字典
print(p1.dang) #先在实例(对象)的__init__的数据属性里找,找不到就找类的数据属性
p1.sui_di_tu_tan() #类的函数属性,会自动把p1传给self
p1.cha_dui() #类的函数属性,会自动把p1传给self
类的增删改查
class Chinese:
councry = "china"
def __init__(self,name):
self.name = name
def paly_ball(self,ball):
print("%s 正在打 %s"%(self.name,ball))
#查看类的数据属性
print(Chinese.councry)
#修改类的数据属性
Chinese.councry = "Japan"
print(Chinese.councry)
# 实例化 创建一个对象
p1 = Chinese("tom")
print(p1.__dict__)
#增加类的数据属性
Chinese.dang = "***"
print(Chinese.dang)
#删除类的数据属性
del Chinese.dang
# 增加类的函数属性
def eat_foot(self,foot):
print("%s 正在吃 %s"%(self.name,foot))
Chinese.eat = eat_foot # 增加类的函数属性
p1.eat("屎")
# 对象调用类的函数属性
p1.paly_ball("篮球")
# 修改类的函数属性
def test(self):
print("test")
Chinese.paly_ball = test #修改类的函数属性
p1.paly_ball()
对象的增删改查
class Chinese:
councry = "china"
def __init__(self,name):
self.name = name
def paly_ball(self,ball):
print("%s 正在打 %s"%(self.name,ball))
p1 = Chinese("tom") #实例化 创建对象
print(p1.__dict__) #查看实例的数据属性
#查看实例的数据属性
print(p1.name)
#增加实例的数据属性
p1.age = 18
print(p1.__dict__)
#删除实例的数据属性
del p1.age
print(p1.__dict__)
#修改实例的数据属性
p1.name = "liaoboshi"
print(p1.__dict__)
特殊的类属性
class ChinesePeople:
'我们都是中国人,我们骄傲的活着,我们不服任何事和物'
government='***'
def sui_di_tu_tan():
print('90%的中国人都喜欢随地吐痰')
def cha_dui(self):
print('一个中国人-->%s<--插到了前面' %self)
print(ChinesePeople.__name__)# 类C的名字(字符串)
print(ChinesePeople.__doc__)# 类C的文档字符串
print(ChinesePeople.__base__)# 类C的第一个父类(在讲继承时会讲)
print(ChinesePeople.__bases__)# 类C的所有父类构成的元组(在讲继承时会讲)
print(ChinesePeople.__dict__)# 类C的属性
print(ChinesePeople.__module__)# 类C定义所在的模块
print(ChinesePeople.__class__)# 实例C对应的类(仅新式类中)
静态属性
class Room:
def __init__(self,name,owner,le,wight,heigh):
self.name = name
self.owner = owner
self.le = le
self.wight = wight
self.heigh = heigh
@property # 静态属性 把函数属性伪装成数据属性
def cal_dz(self):
return (self.le*self.wight*self.heigh)*0.5
r = Room("房间","tom",2,2,2)
print(r.cal_dz)
静态方法
class Room:
tag = 1
def __init__(self,name,owner):
self.name = name
self.owner = owner
@staticmethod #静态方法
def wash_body(a,b,c):
print("洗----->",a,b,c)
Room.wash_body(1,2,3) #类可以使用
r = Room("房间","tom")
r.wash_body(1,2,3) #实例也可以使用
类方法
class Room:
tag = 1
def __init__(self,name,owner):
self.name = name
self.owner = owner
@classmethod # 类方法 专门给类使用,与实例无关 类方法只能访问类相关的属性,不能访问实例属性(与实例无关)
def tell_info(cls):
print(cls)
print("----->",cls.tag)
Room.tell_info()
组合
class School:
def __init__(self,name,addr):
self.name = name
self.addr = addr
def zhao_sheng(self):
print("%s %s 正在招生"%(self.addr,self.name))
class Course:
def __init__(self,name,price,period,school):
self.name = name
self.price =price
self.period = period
self.school = school
s1 = School("oldboy","北京校区")
s2 = School("oldboy","深圳校区")
s3 = School("oldboy","广州校区")
c = Course("python",15800,"5M",s2) #把学校的实例传进去
print(c.__dict__) # 输出 实例c 的属性字典
c.school.zhao_sheng() # 执行 实例s2 的zhao_sheng 函数属性
继承
class Dad:
money = 10
def __init__(self,name):
print("------Dad------")
self.name = name
def hit_son(self):
print("%s 正在打son"%self.name)
class Son(Dad):
money = 10000
s = Son("tom") # 实例Son的类,Son类中没有__init__方法,会调父类中的__init__方法,并且要传父类中要的参数
print(s.money) #===>10000 # 查看Son类的money属性 ,没有会找父类的
s.hit_son() #===>tom 正在打son # 调用Son类的hit_son方法,没有会找父类的
print(Dad.money) #===>10 # 子类和父类都有money的属性,子属的money属性不会覆盖父类的
接口继承
import abc
class All_file(metaclass = abc.ABCMeta):
@abc.abstractmethod #子类要实例化,必须定义用@abc.abstractmethod 修饰的方法
def read(self):
pass
@abc.abstractmethod
def writ(self):
pass
class Disk(All_file):
def read(self):
print("disk read")
def writ(self):
print("disd writ")
class Mem(All_file):
def read(self):
print("mem read")
def writ(self):
print("mem writ")
m = Mem() #想要实例,Mem类必须定义父类用@abc.abstractmethod修饰的方法
m.read()
m.writ()
继承顺序
class A:
def test(self):
print("A")
class B(A):
def test(self):
print("B")
# pass
class C(A):
def test(self):
print("C")
# pass
class D(B):
def test(self):
print("D")
# pass
class E(C):
def test(self):
print("E")
# pass
class F(D,E):
def test(self):
print("F")
# pass
f = F()
f.test() # 继承顺序有 深度优先和广度优先
print("F的继承顺序",F.__mro__) # python3 的继承顺序是广度优先
在子类中调用父类的属性和方法(super方法的使用)
class Vehicle:
councry = "china"
def __init__(self,name,speed,load,power):
self.name = name
self.speed = speed
self.load = load
self.power = power
def run(self):
print("开动了")
print("开动了")
print("开动了")
class Subway(Vehicle):
def __init__(self,name,speed,load,power,line):
# Vehicle.__init__(self,name,speed,load,power) #调用父类的__init__方法,不用再初始化一次
super().__init__(name,speed,load,power) #调用父类的__init__方法,不用再初始化一次
self.line = line
def test(self):
print(self.name,self.speed,self.load,self.power,self.line)
def run(self):
# Vehicle.run(self) # 可以运行子类与父类相同的 run 方法 不会只运行子类的 run 方法
super().run() # 可以运行子类与父类相同的 run 方法 不会只运行子类的 run 方法
print(" %s 开动了"%self.name)
s = Subway("北京地铁","100km/h",500,"电",13) #实例s
s.test() #通过实例s调用Subway的方法
s.run() #通过实例s调用子类和父类的run方法
多态
#类的继承有两层意义:1.改变 2.扩展
#多态就是类的这两层意义的一个具体的实现机制
#即,调用不同的类实例化得对象下的相同的方法,实现的过程不一样
#python中的标准类型就是多态概念的一个很好的示范
class H2o:
def __init__(self,name,wd):
self.name = name
self.wd = wd
def turn_ice(self):
if self.wd < 0 :
print("%s 温度小于0变冰了"%self.name)
elif self.wd >0 and self.wd <100:
print("%s 液化成水了"%self.name)
elif self.wd >100 :
print("%s 温度太高变水蒸气了"%self.name)
class S(H2o):
pass
class Ice(H2o):
pass
class Szq(H2o):
pass
s = S("水",20)
i = Ice("冰",-20)
sz = Szq("水蒸气",120)
def func(obj):
obj.turn_ice()
func(s)
func(i)
func(sz)
封装
class People:
star = "地球"
def __init__(self,id,name,age):
self.name = name
self.id = id
self.age = age
p = People("231243","tom",18)
print(p.star)
class People:
_star = "地球11111"
def __init__(self,id,name,age):
self.name = name
self.id = id
self.age = age
p = People("231243","tom",18)
print(p._star) # _属性名 的属性不建议在外面使用
class People:
__star = "地球222222" # __属性名 python 用自动重命名为 _类名__属性名 __属性名 的属性不建议在外面使用
def __init__(self,id,name,age):
self.name = name
self.id = id
self.age = age
p = People("231243","tom",18)
print(People.__dict__)
print(p._People__star) # __属性名 python 用自动重命名为 _类名__属性名,如果通过 __属性名 会报错
包装标准类型
class List(list):
def append(self, p_object): #修改类List(list父类基础上)的append方法
if type(p_object) is str: #只能添加字符串
super().append(p_object)
else:
print("只能加字符串")
# def min(self): # 在列表类的基础上加了一个可以查到列表中间元素的方法
# i = int(len(self)/2)
# return self[i]
l = List("helloworld")
print(l)
# print(l.min()) #查看中间元素
l.append("tom")
print(l)
反射
class Heizj():
def __init__(self,name,addr):
self.name = name
self.addr = addr
def sell_house(self):
print("%s 正在卖房子"%self.name)
h = Heizj("万盛置地","天露园")
print(hasattr(h,"name")) #检测对象是否有这个属性
#获取对象属性
print(getattr(h,"name")) #获取对象属性
a = getattr(h,"sell_house")
a() #
# print(getattr(h,"fjdiohg")) #获取对象属性,没有这个属性就报错
print(getattr(h,"fjdiohg","123")) #获取对象属性,没有这个属性不报错,会输出第三个参数
setattr(h,"sb","tom") #设置属性,没有这个属性就添加到属性字典里
setattr(h,"name","456") #设置属性,有这个属性,就修改这个属性
print(h.__dict__) #查看属性
delattr(h,"sb") #删除属性
# delattr(h,"fas") #删除属性,没有就报错
print(h.__dict__) #查看属性
双下划线attr方法系列
class Foo:
x = 1
def __init__(self,y):
self.y = y
def __getattr__(self, item):
print("__getattr__运行了")
f = Foo(10)
print(f.x)
f.sssssssss #运行的属性 当类里没有的时候 就自动会运行__getattr__方法
class Foo:
x = 1
def __init__(self,y):
self.y = y
def __delattr__(self, item):
print("__delattr__运行了")
f = Foo(10)
del f.x #一有删除操作就会运行__delattr__方法
del f.y
class Foo:
x = 1
def __init__(self,y):
self.y = y
def __setattr__(self, key, value):
print("__setattr__运行了")
# self.key = value
self.__dict__["key"] = value #设置属性的时候会自动调用__setattr__, 上一行会无限递归,直接设置__dict__不会
f = Foo(10)
print(f.__dict__)
f.z = 5
print(f.__dict__)
双下划线item方法系列
# 触发双下划线item系列,要调用 f1["name"] ,就是要通过中括号去调用才会触发
# 触发双下划线attr系列,要调用 f1.name ,就是要 点 去调用用才会触发
class Foo():
def __getitem__(self, item):
print("__getitem__")
return self.__dict__[item]
def __setitem__(self, key, value):
print("__setitem__")
self.__dict__[key] = value
def __delitem__(self, key):
print("__delitem__")
self.__dict__.pop(key)
f1 = Foo()
print(f1.__dict__)
#f1.name = "tom"
#__setitem__
f1["name"] = "tom"
f1["age"] = 18
print("=====>",f1.__dict__)
#__delitem__
del f1["name"]
print(f1.__dict__)
#__getitem__
print(f1["age"])
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
self.file=open(filename,mode,encoding=encoding)
def write(self,line):
t=time.strftime('%Y-%m-%d %T')
self.file.write('%s %s' %(t,line))
def __getattr__(self, item):
return getattr(self.file,item)
f1=FileHandle('b.txt','w+')
f1.write('你好啊')
f1.seek(0)
print(f1.read())
f1.close()
#授权示范一
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#我们来加上b模式支持
import time
class FileHandle:
def __init__(self,filename,mode='r',encoding='utf-8'):
if 'b' in mode:
self.file=open(filename,mode)
else:
self.file=open(filename,mode,encoding=encoding)
self.encoding=encoding
def write(self,line):
t=time.strftime('%Y-%m-%d %T')
if 'b' in self.mode:
msg=bytes('%s %s' %(t,line),encoding=self.encoding)
self.file.write(msg)
def __getattr__(self, item):
return getattr(self.file,item)
f1=FileHandle('b.txt','wb')
f1.write('你好啊啊啊啊啊') #自定制的write,不用在进行encode转成二进制去写了,简单,大气
f1.close()
#授权示范二
__format__用法
#自定义format练习
date_dic={
'ymd':'{0.year}:{0.month}:{0.day}',
'dmy':'{0.day}/{0.month}/{0.year}',
'mdy':'{0.month}-{0.day}-{0.year}',
}
class Date:
def __init__(self,year,month,day):
self.year=year
self.month=month
self.day=day
def __format__(self, format_spec):
if not format_spec or format_spec not in date_dic:
format_spec='ymd'
fmt=date_dic[format_spec]
return fmt.format(self)
d1=Date(2016,12,29)
print(format(d1))
print(format(d1,"dmy"))
print(format(d1,"mdy"))
__slots__方法
#少用
class Foo:
__slots__ = ["name","age"]
f1 = Foo()
print(Foo.__dict__)
f1.name = "tom"
f1.age = 18
# f1.gender = "man" #不能设置__slots__里没有的属性
print(f1.name)
print(f1.age)
# print(f1.__dict__) #设置了__slots__,实例的对象没有__dict__的属性字典
__del__方法 析构方法
class Foo:
def __del__(self):
print("我执行了")
f1 = Foo()
del f1 #对象被删除时会调用__del__方法
print("-------------->")
#程序运行完时也会调用__del__方法,因为程序运行完,Python解释器会回收对象。
__call__方法
# __module__ 表示当前操作的对象在那个模块
# __class__ 表示当前操作的对象的类是什么
class Foo:
def __call__(self, *args, **kwargs):
print("执行了---")
f1 = Foo()
f1() # f1的类Foo 下的__call__方法. 如果上面没有定义__call__方法,调用f1()用报错
Foo() # Foo的类 XXX 下的__call__方法
一 isinstance(obj,cls)和issubclass(sub,super)
isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object):
pass
obj = Foo()
isinstance(obj, Foo)
issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object):
pass
class Bar(Foo):
pass
issubclass(Bar, Foo)
浙公网安备 33010602011771号