一、封装

'''
1、什么封装
封:属性对外是隐藏的,但对内是开放的(对内是开放的是因为在类定义阶段这种隐藏已经发生改变)
装:申请一个名称空间,往里装入一系列名字/属性 2、为什么要封装
封装数据属性的目的
首先定义属性的目的就是为了给类外部的使用使用的,
隐藏之后是为了不让外部使用直接使用,需要类内部开辟一个接口(就是定义一个接口的函数,然后利用隐藏的原理对其进行封装,这样外部就可以间接使用被隐藏的属性)
然后让类外部的使用通过接口来间接地操作隐藏的属性。
精髓在于:我们可以在接口之上附加任意逻辑,从而严格控制使用者对属性的操作 封装函数属性
首先定义属性的目的就是为了给类外部使用的,
隐藏函数属性是为了不让外不直接使用,需要类内部开辟一个接口(最终还是给外部用的,只是封装成接口,对于使用者来说方便了)
然后在接口内去调用隐藏的功能
精髓在于:隔离了复杂度 3、如何封装 '''
# 如何隐藏:在属性前加上__开头(在类定义阶段这种隐藏已经发生变化为:_类__属性(数据属性/函数属性),这样外部的对象或类也可以使用这种方式直接用,但是没有意义) #1、 这种隐藏仅仅只是一种语法上的变形操作
#2、 这种语法上的变形只在类定义阶段发生一次,因为类体代码仅仅只在类定义阶段检测一次
#3、 这种隐藏是对外不对内的,即在类的内部可以直接访问,而在类的外则无法直接访问,原因是
# 在类定义阶段,类体内代码统一发生了一次变形 #4、 如果不想让子类的方法覆盖父类的,可以将该方法名前加一个__开头 class People:
__country='China' #_People__country='China'
__n=100 #_People__n=100--------------------------------这种类的数据隐藏只是一种语法上的变形
def __init__(self,name,age,sex):
self.__name=name #self._People__name=name----------将对象独有的数据属性进行隐藏,隐藏的本质就是语法上的变形而已
self.age=age
self.sex=sex def eat(self):
print('eat.....') #可以在封装的接口之上添加任意逻辑
print(People.__country) #People._People__country----类内部任然可以通过该隐藏的形式进行调用类隐藏的数据属性
print(self.__name) #self._People__name--------------在内部可以直接用,是因为在定义阶段,这种内部的调用,也发生了语法上的变形 # People.eat(123) #类来调用类的函数属性,就是一个普通的函数,按照函数的传参方式传参即可
'''会报类没有__country这个属性,因为在定义阶段这个属性已经变形为_People__country,所以想条用该属性,就要以变形后的属性调用,才能在类的名称空间中找到这个属性的名字'''
print(People.__country) #-----------在定义阶段隐藏的数据属性已经发生变形,所以此时在类的外部直接调用类隐藏的属性,就会报错 peo1=People('egon',18,'male')
peo1.eat() #------------此时对象直接掉封装接口的函数属性,就可以间接的调用隐藏的数据数据属性
print(peo1.__name) #------------对象的独有的数据属性在定义阶段已经变形,所以此时在类的外部直接调用任然会报错,找不到该属性 print(People.__dict__) #------------通过查看类的字典属性,可以看到,数据隐藏的数据属性,都已经发生变形
print(People.__country) #-----------该类的数据属性在定义阶段已经发生变化,所以此时来调用会报错,没有这个属性
print(People._People__country) #类直接调用类定义阶段已经变形后的数据属性,此时在类的名称空间中就可以找到这么一个属性名,所以能拿到属性名对应的属性值 People.__n=11 #-----------此时看似是对隐藏的属性值进行修改,实际上在类的名称空间中,添加类一个新的属性,因为此时隐藏的属性名已经发生了变形
print(People.__dict__) #字典属性有{'_People__n': 100,'__n': 11}---------可以看到并没有修改隐藏的数据属性的值,可以通过People._People__n=11,完成真正意义的修改 peo1=People('egon',18,'male')
print(peo1.__dict__) #-----{'_People__name': 'egon', 'age': 18, 'sex': 'male'}
peo1.__x=111 #------只是单纯的在对象的名称空间中添加了一个__x的数据属性名字
print(peo1.__dict__) #-----{'_People__name': 'egon', 'age': 18, 'sex': 'male', '__x': 111}
peo1.__name=111 #------只是单纯的在对象的名称空间中添加了一个__name的数据属性名字,并不会改变被隐藏了数据属性的值,因为此时被隐藏的数据属性名已经发生变形
print(peo1.__dict__) #-----{'_People__name': 'egon', 'age': 18, 'sex': 'male', '__x': 111, '__name': 111} # 属性封装在应用
class Foo:
def __f1(self): #_Foo__f1
print('Foo.f1') def f2(self): #对隐藏类的函数属性封装成接口
print('Foo.f2')
self.__f1() #self._Foo__f1 class Bar(Foo):
def __f1(self): #_Bar__f1
print('Bar.f1') # obj=Bar()
# obj.f2() #从对象自己找f1函数属性,没有到自己的类找,自己的类没有到父类中找,找到了是一个封装的接口,
# 调用后又调用了self__f1,此时的属性已经变成了self._Foo__f1,所以不会回到子类中去找,最终找的是Foo中的__f1 '''
Foo.f2
Foo.f1 ''' class People:
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 type(name) is not str:
# print('用户名必须为str类型')
# return
raise TypeError('用户名必须为str类型') #条件成立,raise就会被执行,抛出我们设定的异常
if type(age) is not int:
# print('年龄必须为int类型')
# return
raise TypeError('年龄必须为int类型') #条件成立,raise就会被执行,抛出我们设定的异常
'''-----------------在接口之上添加任意逻辑-----------------'''
self.__name=name #在定义阶段已经发生变化,外部对象或类直接调用接口,就可以间接调用隐藏的数据属性
self.__age=age peo1=People('egon',18) #调用类产生空对象,并给对象的数据属性进行初始化
# peo1.name #对象的数据属性已经被隐藏,此时直接调用会报错,没有该属性
# peo1.age
peo1.tell_info() #通过接口,我们通过对象直接调用接口,就可以很容易拿到被隐藏的数据属性
#
peo1.set_info('egon',19) #通过接口也很容易对隐藏的数据属性的值进行修改
peo1.tell_info()

二、property

#property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接引用
class People:
def __init__(self,name,weight,height):
self.name=name
self.weight=weight
self.height=height @property #把一个函数属性伪装成一个数据属性,这样的好处就是无论是对象还是类来调用,就和访问数据属性一样,不用加括号,就和加括号访问的效果一样
def bmi(self): #将bim这个函数属性伪装成了一个数据属性
return self.weight / (self.height ** 2) peo1=People('egon',75,1.8) peo1.height=1.85
print(peo1.bmi) #用@property 装饰之后,再访问类的函数属性,就不需要加括号了 class People:
def __init__(self,name):
self.__name=name
#伪装到底
@property # 查看obj.name
def name(self): #将name这个函数属性,伪装成了数据属性
return '<名字是:%s>' %self.__name #类内部引用隐藏的数据属性,自身也在定阶段发生了变形 @name.setter #修改obj.name=值
def name(self,name):
if type(name) is not str:
raise TypeError('名字必须是str类型傻叉')
self.__name=name @name.deleter #删除del obj.name
def name(self):
# raise PermissionError('不让删')
print('不让删除傻叉')
# del self.__name peo1=People('egon')
print(peo1.name) #<名字是:egon>----查看伪装的函数属性,此时不用加括号 peo1.name='EGON'
print(peo1.name) #<名字是:EGON>----修改伪装的函数属性,像修改数据属性一样修改即可 del peo1.name
print(peo1.name) #不让删除傻叉、<名字是:EGON>,像删除数据属性一样 # 了解:以前的property以前的用法,和上面装饰器的方法效果一样
class People:
def __init__(self,name):
self.__name=name def tell_name(self):
return '<名字是:%s>' %self.__name def set_name(self,name):
if type(name) is not str:
raise TypeError('名字必须是str类型傻叉')
self.__name=name def del_name(self):
print('不让删除傻叉') name=property(tell_name,set_name,del_name) peo1=People('egon')
print(peo1.name)
peo1.name='EGON'
print(peo1.name)
del peo1.name

三、绑定方法和非绑定方法

'''
1、绑定方法
特性:绑定给谁就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入
《《《精髓在于自动传值》》》 绑定方法分为两类:
1.1 绑定给对象方法
在类内部定义的函数(没有被任何装饰器修饰的),默认就是绑定给对象用的
1.2 绑定给类的方法:
在类内部定义的函数如果被装饰器@classmethod装饰,
那么则是绑定给类的,应该由类来调用,类来调用就自动将类当作第一个参数自动传入 2、非绑定方法
类中定义的函数如果被装饰器@staticmethod装饰,那么该函数就变成非绑定方法
既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用
但是无论谁来调用,都没有任何自动传值的效果,就是一个普通函数 3 应用
如果函数体代码需要用外部传入的类,则应该将该函数定义成------------------------------绑定给类的方法
如果函数体代码需要用外部传入的对象,则应该将该函数定义成----------------------------绑定给对象的方法
如果函数体代码既不需要外部传入的类也不需要外部传入的对象,则应该将该函数定义成-------非绑定方法/普通函数 ''' class Foo:
@classmethod
def f1(cls):
print(cls) def f2(self):
print(self) obj=Foo()
print(obj.f2) #没有被@classmethod装饰,默认就是绑定给对象用的,<bound method Foo.f2 of <__main__.Foo object at 0x0000018370835DD8>>
print(Foo.f1) #被@classmethod装饰,则是绑定给类用的,<bound method Foo.f1 of <class '__main__.Foo'>>
#
Foo.f1() #绑定给类用的,类来调用,会将类自动传出,所以打印结果是:<class '__main__.Foo'>
print(Foo) #直接打印类的结果也是:--------------------------------<class '__main__.Foo'> #1、f1绑定给类的
# 了解:绑定给类的应该由类来调用,但对象其实也可以使用,只不过自动传入的仍然是类
# print(Foo.f1)
# print(obj.f1)
# Foo.f1()
# obj.f1() #2、f2是绑定给对象的
# obj.f2() #没有被装饰,默认是绑定给对象的,会将对象自动传入,<__main__.Foo object at 0x000001BE8FB55DD8>
# Foo.f2(obj) #类来调用,就是一个普通的函数,需要将对象手动传入,打印结果也是:<__main__.Foo object at 0x000001BE8FB55DD8> # 配置文件信息:
'''
IP='1.1.1.10'
PORT=3306
''' import settings
import uuid class Mysql:
def __init__(self,ip,port):
self.uid=self.create_uid() #--------给对象添加一个uid属性,这个属性即create_uid() ,是一个函数
self.ip=ip
self.port=port def tell_info(self):
print('%s:%s' %(self.ip,self.port)) @classmethod #-------------绑定给类的方法
def from_conf(cls):
return cls(settings.IP, settings.PORT) @staticmethod #-------------非绑定方法
def func(x,y):
print('不与任何人绑定') @staticmethod #-------------非绑定方法
def create_uid():
return uuid.uuid1() #uuid1是基于时间戳 # 默认的实例化方式:类名(..)
obj=Mysql('10.10.0.9',3307) # 一种新的实例化方式:从配置文件中读取配置完成实例化
obj1=Mysql.from_conf()
obj1.tell_info() #将对象自动传入,从配置文件中读取的结果是:1.1.1.10:3306 # obj.func(1,2) #不与任何人绑定-----非绑定方法,就是一个普通的函数,对象和类都可以来调用,没有自动传值这么一说,函数需要几个参数就要传几个参数
# Mysql.func(3,4) #不与任何人绑定
# print(obj.func) #<function Mysql.func at 0x0000018974B6BA60>------非绑定方法,无论是对象还是类来调用都只是一个普通的函数
# print(Mysql.func) #<function Mysql.func at 0x0000018974B6BA60> print(obj.uid) #9e20bdde-7aae-11e8-9065-485ab6d4e9f8

Python面向对象之封装、property特性、绑定方法与非绑定方法的更多相关文章

  1. day22-类的封装、property特性以及绑定方法与非绑定方法

    目录 类的封装 两个层面的封装 第一个层面 第二个层面 封装的好处 私有模块 类的propertry特性 setter 和 deleter 类与对象的绑定方法与非绑定方法 类的封装 将类的属性或方法隐 ...

  2. 类的封装,property特性,类与对象的绑定方法和非绑定方法,

    类的封装 就是把数据或者方法封装起来 为什么要封装 封装数据的主要原因是:保护隐私 封装方法的主要原因是:隔离复杂度(快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了,比如你 ...

  3. python 类的封装/property类型/和对象的绑定与非绑定方法

    目录 类的封装 类的property特性 类与对象的绑定方法与非绑定方法 类的封装 封装: 就是打包,封起来,装起来,把你丢进袋子里,然后用绳子把袋子绑紧,你还能拿到袋子里的那个人吗? 1.隐藏属性和 ...

  4. 1.面向过程编程 2.面向对象编程 3.类和对象 4.python 创建类和对象 如何使用对象 5.属性的查找顺序 6.初始化函数 7.绑定方法 与非绑定方法

    1.面向过程编程 面向过程:一种编程思想在编写代码时 要时刻想着过程这个两个字过程指的是什么? 解决问题的步骤 流程,即第一步干什么 第二步干什么,其目的是将一个复杂的问题,拆分为若干的小的问题,按照 ...

  5. Python开发基础-Day21多态与多态性、绑定方法和非绑定方法

    多态与多态性 多态 多态并不是一个新的知识 多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承 举个栗子:动物有多种形态,人.狗.猫.猪等,python的序列数据类 ...

  6. Python面向对象高级编程-@property

    使用@property 在绑定属性时,如果直接把属性暴露出去,虽然写起来简单,但是没法检查参数,导致可以把成绩随便改: >>> class Student(object): pass ...

  7. python基础之多态与多态性、绑定方法和非绑定方法

    多态与多态性 多态 多态并不是一个新的知识 多态是指一类事物有多种形态,在类里就是指一个抽象类有多个子类,因而多态的概念依赖于继承 举个栗子:动物有多种形态,人.狗.猫.猪等,python的序列数据类 ...

  8. Python面向对象04 /封装、多态、鸭子类型、类的约束、super

    Python面向对象04 /封装.多态.鸭子类型.类的约束.super 目录 Python面向对象04 /封装.多态.鸭子类型.类的约束.super 1. 封装 2. 多态 3. 鸭子类型 4. 类的 ...

  9. 全面解析python类的绑定方法与非绑定方法

    类中的方法有两类: 绑定方法 非绑定方法 一.绑定方法 1.对象的绑定方法 首先我们明确一个知识点,凡是类中的方法或函数,默认情况下都是绑定给对象使用的.下面,我们通过实例,来慢慢解析绑定方法的应用. ...

随机推荐

  1. CSS学习摘要-定位实例

    CSS学习摘要-定位实例 注:全文摘自MDN-CSS定位实例 列表消息盒子 我们研究的第一个例子是一个经典的选项卡消息框,你想用一块小区域包括大量信息时,一个非常常用的特征.这包括含有大信息量的应用, ...

  2. 修改Linux SSH连接端口和禁用IP,安装DDoS deflate

    测试系统:centos7 修改连接端口 修改配置文件 vi /etc/ssh/sshd_config 去掉port 22的注释,添加新的端口配置 port your_port_num 自定义端口选择建 ...

  3. JVM虚拟机21: 1.8中废弃永久代(PermGen)迎来元空间(Metaspace)

    1.JDK8永久代的废弃 JDK8 永久代变化如下图: 1.新生代:Eden+From Survivor+To Survivor 2.老年代:OldGen 3.永久代(方法区的实现) : PermGe ...

  4. BZOJ1022:[SHOI2008]小约翰的游戏John(博弈论)

    Description 小约翰经常和他的哥哥玩一个非常有趣的游戏:桌子上有n堆石子,小约翰和他的哥哥轮流取石子,每个人取的时候,可以随意选择一堆石子,在这堆石子中取走任意多的石子,但不能一粒石子也不取 ...

  5. 1084. [SCOI2005]最大子矩阵【网格DP】

    Description 这里有一个n*m的矩阵,请你选出其中k个子矩阵,使得这个k个子矩阵分值之和最大.注意:选出的k个子矩阵 不能相互重叠. Input 第一行为n,m,k(1≤n≤100,1≤m≤ ...

  6. Day18 (二)反射

    反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java ...

  7. 分布式唯一ID的几种生成方案

    前言 在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等.那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十 ...

  8. 详解Tensorflow数据读取有三种方式(next_batch)

    转自:https://blog.csdn.net/lujiandong1/article/details/53376802 Tensorflow数据读取有三种方式: Preloaded data: 预 ...

  9. composer设置国内镜像

    使用composer时,输入命令执行后半天没有反应,并最后是失败的消息. 如下载项目中的框架文件时: composer install 一直没有反应 [注]添加参数-vvv可尽可能多的输出执行信息,帮 ...

  10. java集合(类似python的列表)

    一:学习方法 我们在学习一个类的时候,如果他是期其他类的实现类,我们在学习的时候,先学习他的共同的继承类,学习他们共有的方法,在学习他实现类的特殊方法.由共性--->特殊. 二:集合 1.集合和 ...