zoukankan      html  css  js  c++  java
  • python之路---封装

    【封装】

             隐藏对象的属性和实现细节,仅对外提供公共访问方式。

    【好处】 

    1. 将变化隔离; 

    2. 便于使用;

    3. 提高复用性; 

    4. 提高安全性;

    【封装原则】

          1. 将不需要对外提供的内容都隐藏起来;

          2. 把属性都隐藏,提供公共方法对其访问。

                                     私有变量和私有方法                             

     私有变量                              

    class Person:
        def __init__(self,name):
            self.__name = name
        def __eat(self):
            print( "{} is pig".format(self.__name))     # 类里可以使用私有属性
    p = Person('femgyu')
    # print(p.__name)       # 无法调用私有方法
    print(p._Person__name)  # fengyu         变形后可以调用,但是这种方法不提倡,因为私有属性或方法就不应该在类外面调用
    # p.__eat()             # 无法调用私有方法
    p._Person__eat()        # femgyu is pig  变形后可以调用,但是这种方法不提倡,因为私有属性或方法就不应该在类外面调用

    这种自动变形的特点:

    1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。

    2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。

    3.在子类定义的__x不会覆盖父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。

    针对上面的3,有一道经典面试题

    class A:
        def __init__(self):
            self.__func()
        def __func(self):
            print('A')
    class B(A):
        def __func(self):
            print('B')
    B()
    
    
    # 对比下面的代码
    
    class A:
        def __init__(self):
            self.func()
        def func(self):
            print('A')
    class B(A):
        def func(self):
            print('B')
    B()

    这种变形需要注意的问题是:

    1.这种机制也并没有真正意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N

    2.变形的过程只在类的内部定义私有属性(或方法)时生效,在类外部定义私有属性(或方法)时,不会变形

    class Person:
        def __init__(self,name):
            self.__name = name
        def __eat(self):
            print( "{} is pig".format(self.__name))     # 类里可以使用私有属性
    p = Person('femgyu')
    print(p.__dict__)
    p.__age = 20
    print(p.__dict__)
    
    # 打印结果如下:
    {'_Person__name': 'femgyu'}
    {'_Person__name': 'femgyu', '__age': 20}

     私有方法                                          

    在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    #正常情况
    >>> class A:
    ...     def fa(self):
    ...         print('from A')
    ...     def test(self):
    ...         self.fa()
    ... 
    >>> class B(A):
    ...     def fa(self):
    ...         print('from B')
    ... 
    >>> b=B()
    >>> b.test()
    from B
     
    
    #把fa定义成私有的,即__fa
    >>> class A:
    ...     def __fa(self): #在定义时就变形为_A__fa
    ...         print('from A')
    ...     def test(self):
    ...         self.__fa() #只会与自己所在的类为准,即调用_A__fa
    ... 
    >>> class B(A):
    ...     def __fa(self):
    ...         print('from B')
    ... 
    >>> b=B()
    >>> b.test()
    from A

                                   三个装饰器函数                                    

     property属性            将方法伪装成属性                           

    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:

    class Student(object):
        def get_score(self):
            return self.score
    
        def set_score(self, value):
            if not isinstance(value, int):
                raise ValueError('score must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self.score = value
    s = Student()
    s.set_score(99)
    print(s.get_score())
    
    # 可以任意修改分数
    s.score = 1000
    print(s.get_score())

    这显然不合逻辑。

    class Student(object):
        def get_score(self):
            return self._score
    
        def set_score(self, value):
            if not isinstance(value, int):
                raise ValueError('score must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self._score = value
    s = Student()
    s.set_score(60)
    print(s.get_score())
    
    # 设为私有属性后,就不可以随便修改分数了
    s.__score = 1000
    print(s.get_score())

    但是,上面的调用方法略显复杂,没有直接用属性这么直接简单。

    还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

    @property的实现比较复杂,我们先考察如何使用:

      把一个getter方法变成属性,只需要加上@property就可以了,

      此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值。

    class Student(object):
    
        @property
        def score(self):
            return self._score
    
        @score.setter
        def score(self, value):
            if not isinstance(value, int):
                raise ValueError('score must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('score must between 0 ~ 100!')
            self._score = value
    s = Student()
    
    # 将方法变成属性进行赋值
    s.score = 60
    print(s.score)
    
    s.__score = 1000
    print(s.score)

      classmethod               (类方法)              

    类方法:类中的方法传入类cls,不传对象self

        类中的方法不需要对象去调用,不需要去实例化一个对象,直接用类名调用

    class A():
        role = 'dog'
    
        @classmethod
        def func(cls):
            print(cls.role)
    
    A.func()

     staticmethod                    (静态方法)            

    静态方法:类中的方法不需要传入对象self或者类cls

           直接用类名或对象名调用

    静态方法就是在类里面定义的普通函数,但也是该类的局部函数。

    class A:
        role = 'dog'
    
        @staticmethod
        def func():
            print(A.role)
    
    A.func()
  • 相关阅读:
    ERROR Function not available to this responsibility.Change responsibilities or contact your System Administrator.
    After Upgrade To Release 12.1.3 Users Receive "Function Not Available To This Responsibility" Error While Selecting Sub Menus Under Diagnostics (Doc ID 1200743.1)
    产品设计中先熟练使用铅笔 不要依赖Axure
    12.1.2: How to Modify and Enable The Configurable Home Page Delivered Via 12.1.2 (Doc ID 1061482.1)
    Reverting back to the R12.1.1 and R12.1.3 Homepage Layout
    常见Linux版本
    网口扫盲二:Mac与Phy组成原理的简单分析
    VMware 8安装苹果操作系统Mac OS X 10.7 Lion正式版
    VMware8安装MacOS 10.8
    回顾苹果操作系统Mac OS的发展历史
  • 原文地址:https://www.cnblogs.com/yanyufeng/p/9630113.html
Copyright © 2011-2022 走看看