面向对象(object oriented)
对象就是将属性与功能封装在一起,实际上对象本身的概念就体现了封装
面向对象的封装有三种方式:
- public
公开:不封装,对外公开 - protected
受保护:对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开 - private
私有化:这种封装对谁都不公开
属性和功能的隐藏
也叫私有变量和私有方法
python在定义对象的时候能够隐藏属性和功能,被隐藏的功能在定义之后无法从外部获得
class A:
__N=0 # 变形为_A__N,成为隐藏属性
def __init__(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形
self.__x=10 # 变形为self._A__x
def __f1(self): # 变形为_A__f1
print('__f1 run')
def f2(self): # 定义函数时,会检测函数语法,所以__开头的属性也会变形
self.__f1() # 变形为self._A__f1()
print(A.__N) # 报错AttributeError:类Foo没有属性__N
obj = A()
print(obj.__x) # 报错AttributeError:对象obj没有属性__x
print(obj._A__N) # 能够直接进行访问
'''
隐藏属性和隐藏函数介绍:
隐藏属性实际上是在函数定义时完成的变形
函数定义时会将定义时前面带有双下划线的属性和函数包装成“_类名__属性”的形式
这种做法在一定程度上隐藏了属性和函数,在外部无法直接访问,但是一旦掌握原理,通过“_类名__属性”还是能够访问到的
实际上在应用时这是一种约定俗成,放你看到下划线定义隐藏属性和函数的时候,记得不要将其进行更改
'''
# 隐藏的目的实际上是为了使用
class Teacher:
def __init__(self,name,age): # 将名字和年纪都隐藏起来
self.__name=name
self.__age=age
def tell_info(self): # 对外提供访问老师信息的接口
print('姓名:%s,年龄:%s' %(self.__name,self.__age))
def set_info(self,name,age): # 对外提供设置老师信息的接口
if not isinstance(name,str): # 判断变量name的类型
raise TypeError('姓名必须是字符串类型')
if not isinstance(age,int):
raise TypeError('年龄必须是整型')
self.__name=name
self.__age=age
t=Teacher('lilei',18)
t.set_info(‘LiLei','19') # 年龄不为整型,抛出异常
# Traceback (most recent call last):
TypeError: 年龄必须是整型
t.set_info('LiLi',19) # 名字为字符串类型,年龄为整形,可以正常设置
t.tell_info() # 查看老师的信息
# 姓名:LiLei,年龄:19
@property
@property是一个装饰器,作用是将一些函数功能封装成属性,这种需求我们经常遇到,比如说圆的面积或者周长,我们得到的数据可能是一个半径,但是需要的面积,并且计算的方法是固定的,这时将函数封装成属性更加的方便并且不易被篡改,这体现的也是封装的思想
Class Circle:
def __init__(self,r):
self.r=r
@property
def square(self):
self.square=pi*self.r*self.r
c1=Circle(3)
print(c1.square) # 直接返回面积
# property函数还提供了修改和删除的方法
class Foo:
def __init__(self,val):
self.__NAME=val # 将属性隐藏起来
@property
def name(self):
return self.__NAME
@name.setter
def name(self,value):
if not isinstance(value,str): #类型检查
raise TypeError('%s must be str' %value)
else:
self.__NAME=value
@name.deleter
def name(self):
raise PermissionError('Do not delete')
f=Foo('lili') # 实例化
f.name# 查看对象的属性
f.name='LiLi' # 触发name.setter装饰器对应的函数name(f,’LiLi')
del f.name # 触发name.deleter对应的函数name(f),抛出异常PermissionError
类方法@classmethod
类方法是一个非常典型的绑定方法,将方法绑定给类
'''
类方法的作用是将某一个方法绑定给类
类属性的时候是直接在类下面创建属性
像下面的role属性,类属性与其类似
class Classmethod_Demo():
role = 'dog'
@classmethod
def func(cls):
print(cls.role)
Classmethod_Demo.func() # 类方法可以由直接进行调用
'''
绑定到类的方法就是类专用的,虽然对象也可以调用,但是自动传入的第一个参数仍然是类本身,也就是说这种调用没有意义
静态方法@staticmethod
静态方法是一种非绑定方法,该方法不与类或对象绑定,类与对象都可以来调用它,但它就是一个普通函数而已,因而没有自动传值那么一说
'''
静态方法是直接在类中定义一个方法,这个方法谁都可以使用
class Staticmethod_Demo():
role = 'dog'
@staticmethod
def func():
print("当普通方法用")
Staticmethod_Demo.func()
静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互
即在静态方法中,不会涉及到类中的方法和属性的操作
可以理解为,静态方法是个独立的、单纯的函数,它仅仅托管于某个类的名称空间中,便于使用和维护
'''