zoukankan      html  css  js  c++  java
  • day 23 封装之如何隐藏、封装之隐藏属性的底层原理、封装的真正意义、property特性、绑定方法与非绑定方法

    1、什么是封装

    封:属性对外是隐藏的,但对内是开放的

    装:申请一个名称空间,往里面装入一系列名字/属性

    为什么要封装

      封装数据属性的目的,首先定义属性的目的就是为了给类外部的使用而使用的。

      隐藏之后为了不让外部使用直接使用,需要类内部开辟一个接口

      然后让类外部的使用通过接口来间接地操作隐藏的属性‘

      精髓在于:我们可以在接口之上附加任意逻辑,从而严格控制使用者对属性的操作’

    封装函数属性

      首先定义函数的目的就是为了给类的外部来使用,

      隐藏函数属性是为了不让外部直接使用,需要类内部开辟一个借口

      然后再接口内去调用隐藏的功能

      精髓在于:隔离了复杂度

    #如何隐藏?:在属性前加上__开头
    #这种隐藏是对外不对内的,即在类的内部可以直接访问,而在类的外部无法直接访问
    class people:#只有装的概念没有封的概念
        __country='china'
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def eat(self):
            print('eat...')
            print(people.__country)
    # print(people.eat(123))
    #如何隐藏一个属性,对外隐藏对内开放?
    
    # people.eat(123)#对内是开放的
    # print(people.__country) #对外是封闭的
    peo1=people('egon',18,'male')
    peo1.eat()
    # print(peo1.name) 

    封装之隐藏属性的底层原理

    class people:
        __country='china'
        __n=100
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def eat(self):
            print('eat...')
            print(people.__country)
            print(self.__name)
    
    print(people.__dict__)
    #print(people._people__country) 属性名变成了__people__country
    
    '''
    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) #内部访问(访问的到)
    # print(People.__country)#外部访问,访问不到
    
    # peo1=People('egon',18,'male')
    # peo1.eat()
    # print(peo1.__name)
    
    # print(People.__dict__)
    # print(People.__country)
    # print(People._People__country)
    
    # People.__x=11
    # print(People.__dict__)
    
    
    # peo1=People('egon',18,'male')
    # print(peo1.__dict__)
    # peo1.__x=111
    # print(peo1.__dict__)
    
    # 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()
    

     函数的封装

    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()
    

    封装的真正意义

    pass

    property特性

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

    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
        @property #把bim技能伪装成特征
        def bmi(self):
            return self.weight / (self.height**2)
    
    p1=People('egon',75,1.85)
    print(p1.bmi)      #原本print(peo1.bmi())
    

     详细理解的地方

    property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不用加括号而直接引用
    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
    
        @property
        def bmi(self):
            return self.weight / (self.height ** 2)
    
    peo1=People('egon',75,1.8)
    
    peo1.height=1.85
    print(peo1.bmi)
    
    #关于改技能的属性 ''' class People: def __init__(self,name): self.__name=name @property # 查看obj.name def name(self): 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) # print(peo1.name) # peo1.name='EGON' # print(peo1.name) del peo1.name ''' 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 定位到属性操作三个点,查看 修改 删除
    class People:
        def __init__(self,name):
            self.__name=name
    
        @property # 查看obj.name
        def name(self):
            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)
    
    # 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):#b绑定给对象的
            print(self)
    
    
    obj=Foo()
    # print(obj.f2)#绑定给对象
    # print(Foo.f1)#绑定给类的   不加@classmethod就是访问一个普通的函数
    
    #绑定一共分为两类,一类是绑定给类的,一类是绑定给对象的
    
    # Foo.f1()
    # print(Foo)
    
    
    # 1、f1绑定给类的
    # 了解:绑定给类的应该由类来调用,但对象其实也可以使用,只不过自动传入的仍然是类
    # print(Foo.f1)
    # print(obj.f1)
    # Foo.f1()
    # obj.f1()
    #
    # 2、f2是绑定给对象的
    # obj.f2()
    # Foo.f2(obj)
    #
    import setting
    # import uuid
    #
    class Mysql:
        def __init__(self,ip,port):
            self.uid=self.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()
    #
    # # 默认的实例化方式:类名(..)
    # obj=Mysql('10.10.0.9',3307)
    
    # 一种新的实例化方式:从配置文件中读取配置完成实例化
    # obj1=Mysql.from_conf()
    # obj1.tell_info()
    
    # obj.func(1,2)
    # Mysql.func(3,4)
    # print(obj.func)
    # print(Mysql.func)
    
    print(obj.uid)
    
    视频最后有老师总结
    

      

  • 相关阅读:
    spring_three
    报错:java.sql.SQLException: The server
    Spring_two
    Spring_One
    Mybatis中的collection和association一关系
    Mybatis_three
    文件操作1
    面向对象编程三大特征7
    面向对象编程三大特征6
    面向对象编程三大特征5
  • 原文地址:https://www.cnblogs.com/wangmiaolu/p/9240407.html
Copyright © 2011-2022 走看看