python封装与绑定方法

封装分两个层面:

1创建类的时候,分别创建两者的名称空间,只能通过类名加"."或者object.的方式来访问里面的名字

2,类中把某些属性和方法隐藏起来,或者定义为私有,只有类的内部使用,在类的外部无法使用,

或者留下少数的接口(函数)供外使用

但是无论哪种层面的封装都要对外提供好访问内部隐藏内容的接口

在python中,使用双下划线的方式实现隐藏功能(设置成私有的属性)

在python中隐藏类的私有属性用什么方法呢??

class Teacher:
    def __init__(self,name,age,course):
        self.name=name
        self.age=age
        self.course=course

    def teach(self):
        print("%s is teaching"%self.name)

class Student:
    def __init__(self,name,age,group):
        self.name=name
        self.age=age
        self.group=group

    def study(self):
        print("%s is studying"%self.name)

t1=Teacher("alex",28,"python")
s1=Student("jack",22,"group2")
print(t1.name,t1.age,t1.course)
print(s1.name,s1.age,s1.group)



把两类长得一些属性隐藏起来后,代码如下:
class Teacher:
    def __init__(self,name,age,course):
        self.__name=name
        self.__age=age
        self.__course=course

    def teach(self):
        print("%s is teaching"%self.__name)

class Student:
    def __init__(self,name,age,group):
        self.__name=name
        self.__age=age
        self.__group=group

    def study(self):
        print("%s is studying"%self.__name)
t1=Teacher("alex",28,"python")
s1=Student("jack",22,"group2")
print(t1.name,t1.age,t1.course)
print(s1.name,s1.age,s1.group)
会出现traceback........因为属性值已经私有.....
可以看到隐藏属性后,再像以前那样访问对象内部的属性,就会返回属性错误,那现在要怎么才能访问其内部属性呢?
现在来查看t1和s1的名称空间
print(t1.__dict__)
{'_Teacher__name': 'alex', '_Teacher__age': 28, '_Teacher__course': 'python'}
print(s1.__dict__)
{'_Student__name': 'jack', '_Student__age': 22, '_Student__group': 'group2'}
print(t1._Teacher__name)
print(t1._Teacher__age)
print(t1._Teacher__course)
这次没有报错了,看来隐藏属性之后可以通过"_类名__属性"的方式来访问其内部的属性值,
来得到和隐藏属性之前,直接查看其内部属性一样的值。
python并不会真的阻止开发人员访问类的私有属性,模块也是遵循这种约定。
很多模块都有以单下划线开头的方法,此时使用
from module import *
时,这些方法是不会被导入的,此时必须要通过
from module import _private_module来倒入这个模块

property装饰:

property装饰器用于将被装饰的方法伪装成一个数据属性,
在使用时可以不用加括号而直接引用

class People:
      def __init__(self,name,weight,height):
          self.name=name
          self.weight=weight
          self.height=height
  
      def bmi(self):
         return self.weight / (self.height**2)
 
 peo=People('张三',130,1.65)
 print(peo.name)   #张三
 print(peo.bmi())   #47.75022956841139
#property装饰器
#是一种封装思想的体现,方便了查 删 改

class people:
    def __init__(self,name):
        self.__name=name

    @property
    def name(self):            #查看obj.name
        return '名字是:%s'%self.__name

    @name.setter              #更改obj.name=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):
        print('不让删除')  #里面可以设定提示
        # del self.__name      #也可以设定直接删除功能

peo=people('张三')
#默认不加@property调用方法为:

peo.name='李四'  #@name.setter 调用了更改
print(peo.name)    #@property 调用了查看                  输出结果:名字是:李四
del peo.name       #@name.deleter  调用了产出的需求       输出结果:不让删除

绑定方法:
特性:绑定给谁就应该由谁来调用,谁来调用就会将谁当做第一个参数

精髓:是在于自动传值
绑定对象的方法:在类内部定义的函数(没有被任何装饰器修饰的),默认是绑定

给对象用的, 绑定给对象的:自动传的是对象的值
绑定给类的方法:在类内部定义的函数如果被装饰器@classmethod装饰,
那么则是绑定给类的,应该由类来调用,类来调用就自动将类当做第一个参数自动传入
绑定给类的:自动传的是类的值

非绑定方法

类中定义的函数如果被装饰器@staticmethod装饰,那么该函数就变成非绑定方法
既不与类绑定,又不与对象绑定,意味着类与对象都可以来调用
但是无论谁来调用,都没有任何自动化传值的效果,就是一个普通函数

什么时候绑定给类? 什么时候绑定给对象?取决于函数体代码
如果函数体代码需要用外部传入的类,则应该将该函数定义成绑定类的方法
如果函数体代码需要用外部传入的对象,则应该将该函数定义成绑定给对象的方法
如果函数体代码既不需要外部传入的类也不需要外部传入的对象,则应该将该函数定义成非绑定方法对象,

#绑定方法初始实例:绑定给类@classmethod

class Foo:
    @classmethod
    def f1(cls):
        print('Foo.f1')
        print(cls)

    def f2(self):
        print(self)
obj=Foo()
# print(obj.f2)   #默认绑定给对象用#<bound method Foo.f2 of <__main__.Foo object at 0x04BACD10>>
# print(Foo.f1)   #绑定给类用 <bound method Foo.f1 of <class '__main__.Foo'>>
Foo.f1()     #类调用
print(Foo)   #所以传入的值就是类的值 <class '__main__.Foo'>

obj.f2()    #对象调用,
print(obj)  #所以传入的值就是对象的值 <__main__.Foo object at 0x04C50EB0>

# f1绑定给类的应该由类来调用,但对象其实也可以使用,只不过自动传入的任然是类
#f2绑定给对象的应该由对象来调用,但是类其实也可以使用
# 绑定方法进阶实例2:新的实例化方式,绑定给类
"""
将需要传入的信息写到settings.py文件里面,调用更加灵活方便
IP='192.168.11.3'
PORT=3306
"""
import settings

class Mysql:
    def __init__(self,ip,port):
        self.ip=ip
        self.port=port
    def tell_info(self):
        print('%s:%s'%(self.ip,self.port))
        # print(self)

    @classmethod
    def from_conf(cls):
        return cls(settings.IP,settings.PORT) #可以理解为 Mysql('1.1.1.1',23)即调用了init方法,给其传参数 cls名字可以随便起
    # print(settings.IP)

#默认的实例化方式:类名(..)(实质给tell_info(self)里的self传的是对象res的值)
res=Mysql('1.1.1.1',23)
print(res)  #<__main__.Mysql object at 0x05717410>即为对象res也就是tell_info(self)的值
res.tell_info()

# 一种新的实例化方式,从配置文件中读取配置完成实例化(这里实质给cls传的是类Mysql的值)
res=Mysql.from_conf()
res.tell_info()
print(res.ip)

扩展模块:有两种

一种是按照代码的规范,用C/C++直接写python模块;
此方法开发出来的扩展模块(DLL动态库),可看做原生的python模块,
不需要依赖其他第三方库;缺点是,开发需要写大量的规范的C/C++到Python的转换代码

第二种是现在有好多的可以直接将python代码转化为cpy的文件,可以直接运行,二进制文件还不可逆,保证了

代码的不泄露

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值