面向对象是一种思想而不是非得用类定义,该思想在于将重复的属性和行为分离出来,所以即使用函数也可以实现面向对象。
# 用函数实现面向对象思想
def school(name,addr,type):
def init(name, addr, type):
sch = {
'name': name,
'addr': addr,
'type': type,
'kao_shi': kao_shi,
'zhao_sheng': zhao_sheng,
}
return sch
def kao_shi(school):
print('%s 学校正在考试' %school['name'])
def zhao_sheng(school):
print('%s %s 正在招生' %(school['type'],school['name']))
return init(name,addr,type)
s1=school('北大','北京','公立学校')
print(s1)
print(s1['name'])
s1['zhao_sheng'](s1)
s2=school('清华','北京','公立学校')
print(s2)
print(s2['name'],s2['addr'],s2['type'])
s2['zhao_sheng'](s2)
由于用函数实现不够方便,
python等语言帮我们提供了类这个概念用来方便实现面向对象编程。
# 在Python中,定义类是通过class关键字:
'''
1.数据属性
2.函数属性
'''
class Chinese: # 定义类 类名一般首字母大写
country='China' # 类的数据属性 也称:属性
def __init__(self,name): # 构造函数
self.name=name # 初始化实例的数据属性
def play_ball(self,ball): # 类的函数属性 也称:方法
print('%s 正在打 %s' %(self.name))
#查看类的属性
print(Chinese.country)
#修改类的属性
Chinese.country='panama'
print(Chinese.country)
# 实例化类的对象
p1=Chinese('alex')
# 用内置的__dict__打印实例的属性字典
print(p1.__dict__)
print(p1.country)
#增加属性
Chinese.groups='汉族'
print(Chinese.groups)
print(p1.groups)
#删除
del Chinese.groups
del Chinese.country
print(Chinese.__dict__)
print(Chinese.country)
# 增加函数属性
def eat_food(self,food):
print('%s 正在吃%s' %(self.name,food))
Chinese.eat=eat_food
print(Chinese.__dict__)
p1.eat('面')
def test(self):
print('test')
# 替换函数
Chinese.play_ball=test
p1.play_ball()# Chinese.play_ball(p1)
类的属性与实例属性易懵点
class Chinese:
country='China'
def __init__(self,name):
self.name=name
def play_ball(self,ball):
print('%s 正在打 %s' %(self.name,ball))
p1=Chinese('alex')
#为P1对象增加country属性,类的country属性不变
print(p1.country) # 输出China
p1.country='Japan'
print(Chinese.country) # China
class Chinese:
country='China'
l=['a','b']
def __init__(self,name):
self.name=name
def play_ball(self,ball):
print('%s 正在打 %s' %(self.name,ball))
p1=Chinese('ndk')
print(p1.l) #['a', 'b']
#为P1对象增加l属性,类的l属性不变
p1.l=[1,2,3]
print(Chinese.l) # ['a', 'b']
# pi对象的属性字典增加了l,
print(p1.__dict__) # {'name': 'ndk', 'l': [1, 2, 3]}
p1.l.append('c')
print(p1.__dict__) # {'name': 'ndk', 'l': [1, 2, 3, 'c']}
print(Chinese.l) # 类的l列表任然不变 ['a', 'b']
#直接append方式没有生产对象的属性,append直接修改到类的属性中去了
p1.l.append('c')
print(Chinese.l) #输出 ['a', 'b', 'c']
# 调用类内还是类外?
# 不用对象或类调用属性的话,解释器不在__dict__字典中查找,直接在全局中找。
country='中国-------------------'
class Chinese:
country='中国'
def __init__(self,name):
self.name=name
print('--->',country) #此处不是用类/对象调用country,则调用外部country
def play_ball(self,ball):
print('%s 正在打 %s' %(self.name,ball))
print(Chinese.__dict__) #{'__module__': '__main__', 'country': '中国', '__init__': <function Chinese.__init__ at 0x00000246E3A40950>, 'play_ball': <function Chinese.play_ball at 0x00000246E4AB01E0>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None}
print(Chinese.country) #中国
p1=Chinese('alex') #输出:---> 中国-------------------
print('实例--------》',p1.country) #实例--------》 中国
实例属性的增删改查
class Chinese:
country='China'
def __init__(self,name):
self.name=name
def play_ball(self,ball):
print('%s 正在打 %s' %(self.name,ball))
p1=Chinese('ndk')
print(p1.__dict__)
#查看
print(p1.name)
print(p1.play_ball)
#增加
p1.age=18
print(p1.__dict__)
print(p1.age)
#不要修改底层的属性字典
p1.__dict__['sex']='male'
print(p1.__dict__)
print(p1.sex)
#修改
p1.age=19
print(p1.__dict__)
print(p1.age)
#删除
del p1.age
print(p1.__dict__)
类的静态属性,静态方法,类方法
#静态方法:@property 将方法修饰为属性
#静态方法@staticmethod 供实例/类调用,不能调用类属性和方法,与类内一般函数相比无self参数,当类内工具包使用
#类方法:@classmethod 将方法修饰为类方法,供实例和类直接调用,默认参数为cls,无self参数
class Room:
tag=1
def __init__(self,name,owner,width,length,heigh):
self.name=name
self.owner=owner
self.width=width
self.length=length
self.heigh=heigh
@property
def cal_area(self):
print('%s 住的 %s 总面积是%s' % (self.owner,self.name, self.width * self.length))
return self.width * self.length
@classmethod
def tell_info(cls,x):
print(cls)
print('--》',cls.tag,x) # print('--》',Room.tag)
def tell_info(self):
print('---->',self.tag)
@staticmethod
def wash_body(a,b,c):
print('%s %s %s正在洗澡' %(a,b,c))
def test(x,y):
print(x,y)
Room.wash_body('abc','123','qaz')
print(Room.__dict__)
r1=Room('公园','哈桑',100,100,100000)
print(r1.__dict__)
r1.wash_body('abc','123','qaz')
# Room.test(1,2) 输出 1 2
# r1.test(1,2) 报错 test() takes 2 positional arguments but 3 were given
类的继承
class Dad:
'这个是爸爸类'
money=10
def __init__(self,name):
print('爸爸')
self.name=name
def hit_son(self):
print('%s 正在打儿子' %self.name)
class Son(Dad):
money = 1000000000009
def __init__(self,name,age):
self.name=name
self.age=age
def hit_son(self):
print('来自儿子类')
print(Son.money) #1000000000009
# Son.hit_son()
print(Dad.__dict__)
print(Son.__dict__)
s1=Son('alex',18)
s1.hit_son() # 来自儿子类
print(s1.money) # 1000000000009
print(Dad.money) # 10
print(s1.name) # alex
print(s1.__dict__) #{'name': 'alex', 'age': 18}
s1.hit_son() # 来自儿子类
类的继承顺序
若有上图所示继承类的顺序:B,C继承自A;D继承自B;E继承自C;F继承自D,E;
则函数查找顺序为如下:
#coding:utf-8
class A:
# def test(self):
# print('A')
pass
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
f1=F()
f1.test()
#经典类:F->D->B->A-->E
# 经典类:没有继承object的类
#新式类:均继承了object的类
# 在python3中全为新式类,可用方法解析序列__mro__查看继承类顺序
print(F.__mro__)
#F-->D->B-->E--->C--->A新式类
接口继承实现归一化
# 导入abc模块实现统一接口函数
import abc
# 标准类继承格式
class All_file(metaclass=abc.ABCMeta):
@abc.abstractmethod
def read(self):
pass
# 用@abc.abstractmethod修饰类方法后子类继承该类时,必须重写该函数
@abc.abstractmethod
def write(self):
pass
class Disk(All_file):
def read(self):
print('disk read')
def write(self):
print('disk write')
class Cdrom(All_file):
def read(self):
print('cdrom read')
def write(self):
print('cdrom write')
class Mem(All_file):
def read(self):
print('mem read')
def write(self):
print('mem write')
m1=Mem()
m1.read()
m1.write()
在子类用super函数中调用父类方法
class Vehicle1:
Country='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('开动啦')
class Subway(Vehicle1):
def __init__(self,name,speed,load,power,line):
# Vehicle.__init__(self,name,speed,load,power)
# super().__init__(name,speed,load,power) #super(__class__,self).__init__(name,speed,load,power)
super(Subway,self).__init__(name,speed,load,power)
self.line=line
def show_info(self):
print(self.name,self.speed,self.load,self.power,self.line)
def run(self):
# Vehicle.run(self)
super().run()
print('%s %s 线,开动啦' %(self.name,self.line))
line13=Subway('北京地铁','10km/s',1000000000,'电',13)
line13.show_info()
line13.run()
print(line13.__class__)
反射的实现: hasattr getsttr setattr delattr
class BlackMedium:
feture='Ugly'
def __init__(self,name,addr):
self.name=name
self.addr=addr
def sell_hourse(self):
print('【%s】 正在卖房子,傻逼才买呢' %self.name)
def rent_hourse(self):
print('【%s】 正在租房子,傻逼才租呢' % self.name)
# 判断是否拥有该属性
print(hasattr(BlackMedium,'feture'))
# 或得该属性对应的值
print(getattr(BlackMedium,'feture'))
b1=BlackMedium('万成置地','天露园')
# b1.name--->b1.__dic__['name']
print(b1.__dict__)
# 设置属性
setattr(b1,'sb',True)
setattr(b1,'sb1',123)
setattr(b1,'name','SB')
# 删除属性
delattr(b1,'sb')
类中带双下划线的attr方法
class Foo:
def __init__(self,name):
self.name=name
# 获取属性时触发
def __getattr__(self, item):
print('你找的属性【%s】不存在' %item)
# 修改属性时触发
def __setattr__(self, k,v):
print('执行setattr',k,v)
if type(v) is str:
print('开始设置')
# self.k=v #触发__setattr__
self.__dict__[k]=v.upper()
else:
print('必须是字符串类型')
# 删除属性时触发
def __delattr__(self, item):
print('不允许删除属性【%s】' %item)
# print('执行delattr',item)
# del self.item
# self.__dict__.pop(item)
f1=Foo('alex')
f1.age=18 #触发__setattr__
print(f1.__dict__)
print(f1.name)
print(f1.age)
print(f1.gender)
print(f1.slary)
print(f1.__dict__)
del f1.name
print(f1.__dict__)
类的封装
#_*_coding:utf-8_*_
#在类中用单下划线_,或双下划线__封装内部属性,只能在内部用访问
#Python的封装是一种约定(实际任然可以在外部访问,这样相当于声明让别人不要在外部访问)
__author__ = 'Linhaifeng'
class People:
__star='earth111111111111'
__star1='earth1111111'
__star2='earth111111111111'
__star3='earth111111111111'
def __init__(self,id,name,age,salary):
print('----->',self.__star)
self.id=id
self.name=name
self.age=age
self.salary=salary
def get_id(self):
print('我是私有方法啊,我找到的id是[%s]' %self.id)
#访问函数
def get_star(self):
print(self.__star)
p1=People('123123123123','alex','18',100000000)
# print(p1.__star)
print(People.__dict__)
# print(p1.__star)
print(p1._People__star) # 在外部访问到了私有属性
#
p1.get_star()
p1.get_star()