面向对象
属性查找
1.先从对象的名称空间找
2.再从对象类的类变量找
3.在找父类的类变量
先对象本身-->类-->父类-->父类的父类-->object-->自己定制的元类-->type
class people():
v_id=0
def __init__(self,name):
self.name=name
class zx(people):
v_id = 1
def __init__(self,name,v_id):
super().__init__(name)
self.v_id=v_id
wl=zx("zx",2)
print(wl.v_id)
2
class people():
v_id=0
def __init__(self,name):
self.name=name
class zx(people):
v_id = 1
def __init__(self,name):
super().__init__(name)
wl=zx("zx")
print(wl.v_id)
1
class people():
v_id=0
def __init__(self,name):
self.name=name
class zx(people):
def __init__(self,name):
super().__init__(name)
wl=zx("zx")
print(wl.v_id)
0
继承
类调用方法,和对象调用方法的区别
类调用方法的需要加上self
这个形参,但是实例化的对象调用的时候不用填写,因为默认把对象本身作为self
这个参数,(这样做有啥好处呢)
class people():
def hello(self):
print("hello")
zx=people()
zx.hello()
people.hello("a")
比如,可以这样用,可以使用对象自身的方法属性
class people():
def __init__(self,age):
self.age=age
def chang_age(self,age):
self.age=age
zx=people(18)
print(zx.age)
zx.chang_age(20)
print(zx.age)
super
在单继承时,super().__init__()
与people.__init__()
是一样的。super()避免了父类的显式调用
class people():
def __init__(self,name):
self.name=name
class student(people):
def __init__(self,name):
people.__init__(self,name)
zx=student("lalal")
print(zx.name)
lalal
多继承遵从__mro__
多态和多态性
多态
多态指的是一类事物的多种形态
1.序列数据类型有多种形态:字符串,列表,元组
2.动物有多种形态:人,狗,猪
增加了程序的灵活性和可扩展性
多态性
注意:多态与多态性是两种概念
多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。(例如len()
)
接口统一的三种方法
1.abc
python中的抽象基类(ABC,Abstract Base Class)相当于是Java中的接口,抽象基类就是定义各种方法而可以不做具体实现的类,当然也可以实现,只不过子类如果想调用抽象基类中定义的方法需要使用super()
import abc
class people(metaclass=abc.ABCMeta):
@abc.abstractmethod
def say(self):
pass
class student(people):
def say(self):
print('hello')
zx=student()
zx.say()
hello
2.抛出异常
class people():
def say(self):
raise Exception("没有重写方法")
class student(people):
def say(self):
pass
zx=student()
zx.say()
3.崇尚鸭子类型:只要走路像鸭子(对象中有某个绑定方法),那你就是鸭子
class student:
def say(self):
print("student")
class teacher:
def say(self):
print("teacher")
def go_say(self):
self.say()
zx=student()
zx2=teacher()
go_say(zx)
go_say(zx2)
{'module': 'main', '_zx__tag': 1, 'init': <function zx.init at 0x000001BFFB376D08>, '_zx__hello': <function zx.__hello at 0x000001BFFB376D90>, 'dict': <attribute 'dict' of 'zx' objects>, 'weakref': <attribute 'weakref' of 'zx' objects>, 'doc': None}
{'_zx__name': 'zx125', '_zx__age': 18}
封装
封装数据的主要原因是:保护隐私
封装方法的主要原因是:隔离复杂度(只要知道怎么使用,不需要知道复杂的实现过程)
两个层面的封装
第一个层面
创建类和对象会分别创建二者的名称空间,我们只能用类名.或者obj.的方式去访问里面的名字,这本身就是一种封装
第二个层面
类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问,或者留下少量接口(函数)供外部访问。
python 中的私有
其实说到底还是约定俗成
class zx:
__tag=1
def __init__(self,name):
self.__name=name
def __hello(self,age):
self.__age=age
z=zx("zx125")
z._zx__hello(18)
print(zx.__dict__)
print(z.__dict__)
python中的get set
@property
.setter
.deleter
class zx:
def __init__(self,name,age):
self.__name=name
self.age=age
@property
def name(self): #相当于get
print(self.__name)
@name.setter #相当于set
def name(self,name):
self.__name=name
@name.deleter
def name(self):
del self.__name
zx125=zx("华盛顿",18)
zx125.name
zx125.name="啊哈哈"
zx125.name
del zx125.name
zx125.name
华盛顿
啊哈哈
print(self.__name)
AttributeError: 'zx' object has no attribute '_zx__name