面向对象
优点:提升程序的解耦合程度,进而增强程序的可扩展性
缺点:设计复杂
对象是‘容器’,用来盛放数据和功能,是一种将数据和功能整合到一起的方法
类也是容器,用来存放同类对象共有的数据和功能
站在程序角度看,类就是一个名称空间,对象也是一个名称空间
类的各个对象中存放各自独有的属性
所以类中最常见的是变量和函数的定义
类的代码在定义阶段就会执行,会产生类的名称空间
类的命名一般用驼峰体
用类创建对象时,底层建立了对象和类的关联,
当查找一个对象的某个属性时,先在这个对象的名称空间里面找,然后去对象的类中查找
1.先定义类
2.调用类的过程又称之为实例化,发生了三件事:
- 先产生一个空对象
- 底层自动执行类的_init_()方法,并且将空对象和调用类时括号内传入的参数传递给init
- 返回初始化后的对象
_init_()方法总结
- _init_()方法用来为对象初始化自己独有的数据
- _init_()方法中的代码一般是为对象初始化属性,也可以将想要在调用类时就执行的代码放进去
- _init_()方法必须返回None
类的属性是共享给所有对象使用的,多个对象访问同一个属性时,访问的是同一地址
绑定方法:在具体对象调用类的某个函数属性时,会将该函数绑定给具体对象,并且将对象本身作为第一个参数自动传递给函数
如何隐藏属性
在类里面的属性,例如:name属性的前面加上__name,这样在类外面就不能直接通过 .__name访问到name属性了,
但是在类里面通过.__name访问到name属性,对外不对内
因为在类的定义阶段,检测类体代码语法时,类里面像__name这样的语法都会变形成:
_类名__属性名,
在类外面可以通过 ._类名__name访问到隐藏的name属性
class foo:
__x=1
def f(self):
print(foo.__x)
print(foo._foo__x) #结果为:1
foo1=foo()
foo1.f() #结果为:1
foo.__y=2 #这个不会变形
隐藏数据属性
将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制
隐藏函数属性
目的的是为了隔离复杂度,
property是一个装饰器,用来将绑定给对象的方法伪装成一个数据属性,后续就可以通过访问属性,修改属性去调用对应的访问方法,修改方法
#写法一
class People:
def __init__(self, name):
self.__name = name
# 访问name属性时执行的代码
@property
def name(self):
print(self.__name)
# 设置name属性值时执行的代码
@name.setter
def name(self, val):
if type(val) is not str:
print('必须输入字符串类型')
return
self.__name = val
# 删除name属性时执行的代码
@name.deleter
def name(self):
print('不能删除')
peo1=People('page')
peo1.name
peo1.name='alex'
peo1.name
del peo1.name
#写法二
class People:
def __init__(self, name):
self.__name = name
def get_name(self):
print(self.__name)
def set_name(self, val):
if type(val) is not str:
print('必须输入字符串类型')
return
self.__name = val
def del_name(self):
print('不能删除')
# 用name这个名字来代替访问name属性时使用get_name(),
# 用name这个名字来代替修改name属性时使用set_name(),
# 用name这个名字来代替删除name属性时使用del_name(),
name = property(get_name, set_name, del_name)
#上面这句代码写在People类内部的效果等价于写法一中的三个装饰器
peo1=People('page')
peo1.name
peo1.name='alex'
peo1.name
del peo1.name