一.封装
面向对象三大特征:
封装,继承,多态
最重要的一个特性就是封装,封装就是把数据和功能整合到一起.所以封装==整合
在封装的基础上,我们可以将装到对象或类中的属性隐藏起来,注意:
(1).在定义或者初始化对象时,在属性前加__,就会将该属性隐藏起来,但该隐藏起始只是一种变形_类名__属性名,并没有真正的隐藏起来
(2)该变形操作是在类定义阶段扫描语法时发生的变形,类定义之后添加的__开头的属性不会发生变形
(3)该隐藏是对外不对内的
(4)在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
例1:
class Student:
__school = 'oldboy' # _Student__school = 'oldboy'
def __init__(self,x,y,z):
self.__name = x # self._Student__name = x
self.age = y
self.gender = z
def __choose(self): # self._Student__choose
print('%s 正在选课' % self.name)
stu_obj1 = Student('冯疯子',18,'female')
# stu_obj1.__x = 111
# print(stu_obj1.__dict__) # {'_Student__name': '冯疯子', 'age': 18, 'gender': 'female', '__x': 111}
# print(stu_obj1.__x) # 111
print(stu_obj1.__dict__) # {'_Student__name': '冯疯子', 'age': 18, 'gender': 'female'}
print(stu_obj1._Student__name) # 冯疯子
print(Student.__dict__) # {'__module__': '__main__', '_Student__school': 'oldboy', '__init__': <function Student.__init__ at 0x000002322B72E550>, '_Student__choose': <function Student.__choose at 0x000002322B8E5040>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
print(Student._Student__school) # oldboy
print(stu_obj1._Student__school) # oldboy
隐藏属性的意义:
1.把数据属性隐藏起来的意义:
在类内开放接口,让外界使用者通过接口来操作属性值,我们可以在接口之上附加任意的逻辑来严格控制外界使用者对属性的操作
2.把功能属性隐藏起来:
隔离复杂度
1.把数据属性隐藏起来的意义:
class Student:
__school = 'oldboy' # _Student__school = 'oldboy'
def __init__(self,x,y,z):
self.__name = x # obj._Student__name = x
self.__age = y
self.gender = z
def __choose(self): # obj.__Student__choose
print('%s 正在选课' % self.name)
def get_name(self):
print(self.__name)
def set_age(self,x):
if type(x) is not int:
print('年龄必须是整型,傻叉')
return
self.__age = x
def get_age(self):
print(self.__age)
def del_age(self):
del self.__age
stu_obj1 = Student('冯疯子',18,'female')
stu_obj1.get_name() # 冯疯子
stu_obj1.set_age('asfdasdf')
# stu_obj1.set_age(19)
# stu_obj1.get_age()
print(stu_obj1.__dict__) # {'_Student__name': '冯疯子', '_Student__age': 18, 'gender': 'female'}
2.把功能属性隐藏起来:隔离复杂度
例如ATM程序的取款功能,该功能有很多其他功能组成,比如插卡、身份认证、输入金额、打印小票、取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用户认证')
def __input(self):
print('输入存款金额')
def __print_bill(self):
print('打印账单')
def __take_money(self):
print('取款')
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
a = ATM()
a.withdraw()
二.property
property这个装饰器,可以将类中的函数“伪装成”对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果
例1:
class People:
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
@property
def bmi(self):
return self.weight / (self.height ** 2)
p = People('egon', 1.81, 70)
p.height = 1.84
print(p.bmi)
例2:
class Student:
__school = 'oldboy'
def __init__(self,x,y,z):
self.__name = x
self.__age = y
self.gender = z
def get_name(self):
print('访问控制')
return self.__name
def set_name(self,x):
print('赋值操作')
self.__name = x
def del_name(self):
print('删除操作')
del self.__name
def get_age(self):
return self.__age
def set_age(self,x):
if type(x) is not int:
print('年龄必须是整型,傻叉')
return
self.__age=x
def del_age(self):
print('不让删')
age = property(get_age,set_age,del_age)
name = property(get_name,set_name,del_name)
stu_obj1 = Student('冯疯子',18,'female')
print(stu_obj1)
stu_obj1.age = '19'
del stu_obj1.age
print(stu_obj1.age)
print(stu_obj1.name)
stu_obj1.name='EGON'
del stu_obj1.name
使用property有效地保证了属性访问的一致性。另外property还提供设置和删除属性的功能
例3:
class Student:
__school = 'oldboy'
def __init__(self,x,y,z):
self.__name = x
self.__age = y
self.gender = z
@property
def name(self):
print('访问控制')
return self.__name
@name.setter
def name(self,x):
print('赋值控制')
self.__name = x
@name.deleter
def name(self):
print('删除控制')
del self.__name
stu_obj1 = Student('冯疯子',18,'female')
stu_obj1.name
三.绑定方法与非绑定方法
类中的定义的函数分为2大类:绑定方法与非绑定方法
1.绑定方法:谁来调用就会将谁当作第一个参数传入
(1)绑定给对象的方法:类中定义的函数默认就是绑定给对象的方法,应该是由对象调用,会把对象当做第一个参数传入
(2)绑定给类的方法:在类中的函数上加一个装饰器@classmethod,该函数就绑定给类了,应该是由类来调用,会把类当做第一个参数传入
2.非绑定方法:既不与类绑定也不与对象绑定,就是一个普通的函数,谁都可以来调用,没有自动传参的效果,在函数上添加装饰器@staticmethod
class People:
def __init__(self,name,age):
self.name = name
self.age = age
def tell_info(self):
print('<%s:%s>'%(self.name,self.age))
@classmethod
def f1(cls):
print(cls)
@staticmethod
def f2(x,y,z):
print(x,y,z)
p1 = People('egon',18)
p1.tell_info() # <egon:18>
print(p1.tell_info) # <bound method People.tell_info of <__main__.People object at 0x000001E0FB535D30>>
print(People.f1) # <bound method People.f1 of <class '__main__.People'>>
People.f1() # <class '__main__.People'>
print(p1.f2) # <function People.f2 at 0x00000116D74E5700>
print(People.f2) # <function People.f2 at 0x00000116D74E5700>
p1.f2(1,2,3) # 123
People.f2(1,2,3) # 123
# settings.py文件内容
IP = "127.0.0.1"
PORT = 3306
import uuid
import settings
class MySQL:
def __init__(self,ip,port):
self.mid=self.__created_id()
self.ip = ip
self.port = port
def tell_info(self):
print('%s:<%s:%s>'%(self.mid,self.ip,self.port))
@staticmethod
def __created_id():
return uuid.uuid4()
@classmethod
def from_conf(cls):
return cls(settings.IP,settings.PORT)
obj = MySQL('10.10.11.11',3306)
obj.tell_info()
obj1 = MySQL.from_conf()
obj1.tell_info()
总结绑定方法与非绑定方法的使用:
若类中需要一个功能,该功能的实现代码中需要引用对象则将其定义成对象方法、
需要引用类则将其定义成类方法、无需引用类或对象则将其定义成静态方法