zoukankan      html  css  js  c++  java
  • python's twenty-second day for me 封装,property方法

    面对对象的三大特性:继承,多态,封装。

      函数和属性装到了一个非全局的命名空间----封装。

    封装:

        在类中,静态属性,方法,对象属性都可以变成私有的,只需要在这些名字前加上‘__’(双下划线)

        在类内,只要你的代码遇到‘__’(双下划线).名字,就会被python解释器自动转换_类名__名字。

    class A:
        __N = 'aaa'     # 静态变量
        def func(self):
            print(A.__N)    # 在类的内部使用正常 ‘aaa’
    print(A.__dict__)   #  会以这种形式存储到字典中:{'_A__N': 'aaa'}
    # print(A.__N)        # 直接在外部调用会报错
    # print(A._A__N)      # 所以可以使用这种方式调用,但是不能这样调用。
    a = A()
    a.func()
    # 一个私有的名字,在存储的过程中仍然会出现在A.__dict__中,所以我们仍然可以调用到。
    # python对其的名字进行了修改:_类名__名字。
    # 只不过在类的外部调用: '_类名__名字'去使用。
    # 在类的内部可以正常的使用名字调用。

      私有的名字不能被子类继承:

    class D:
        def __func(self):       # _D_func
            print('in func')
    class E(D):
        def __init__(self):
            self.__func()     # 它会找   _E__func 这样的名字。
    
    e = E()  #  会报错,因为私有的名字不能被继承,
    class D:
        def __init__(self):
            self.__func()       # 在哪个类中定义的名字就会以固定方式存储: _D__func
        def __func(self):       # _D__func
            print('in D')
    class E(D):
        def __func(self):    # _E__func
            print('in E')
    e = E()
    
    # 私有的名字,在类内使用的时候,就是会变成:   _该类名__方法名
    # 以上为例:没有双下划线会先找E中的func
    # 但是有了双下划线,会在调用这个名字的类D中直接找_D__func
    面试题

      变形只在类的内部发生:

    class F:pass
    F.__name = 'alex'   # 并不是创建私有属性。
    print(F.__name)
    print(F.__dict__)       # {'__name': 'alex'}  并不是私有属性

    Java中的对比:

      public  共有的  在类的内部可以使用,子类可以使用,外部可以使用  python中所有正常的名字。

      prctect  保护的  在类的内部可以使用,子类可以使用,外部不可以使用,  python中没有

      private  私有的  只能在类的内部使用,子类和外部都不可以使用  python中的  __名字。(双下划线)

    私有的用法:

        1,当一个方法不想被子类继承的时候。

      2,有些属性或者方法不希望从外部被调用,只想提供给内部的方法使用。

    @property  能够将一个方法伪装成一个属性。将代码变得更美观。

    从原来的对象的对象名.方法名(),变成了对象名.方法名。

    class Person:
        def __init__(self,name,weight,height):
            self.name = name
            self.__height = height
            self.__weight = weight
        @property
        def bmi(self):
            return self.__weight/self.__height**2
    print(Person.__dict__)
    p = Person('顾小白',70,1.75)
    print(p.__dict__)    #{'name': '顾小白', '_Person__weight': 70, '_Person__height': 1.75}
    # 被property装饰的bmi仍然是一个方法,存在Person.__dict__
    # 对象的.__dict__中不会存储这个属性。
    
    # 在一个类加载的过程中,会先加载这个的名字,包括被property装饰的。
    # 在实例化对象的时候,python解释器会先到类的空间里看看有没有这个被装饰的属性。
    # 如果有就不能在自己的对象空间中创建这个属性了。

    @property ---> func  将方法伪装成属性,只能看,不能对之操作。

    @func.setter ---> func  对伪装的属性进行赋值的时候调用这个方法,一般情况用来修改属性。

    @func.deleter ---> func  在执行del 对象.func的时候调用这个方法,一般情况用来删除属性,一般不用。

    class Person:
        def __init__(self,name):
            self.__name = name   # 私有属性
        @property       # 将方法装饰成属性使用。  现在 p.name 相当于 p.name()
        def name(self):
            return self.__name
        @name.setter
        def name(self,new_name):
            if type(new_name) is str:       # 类型不对无法替换,防止乱改。
                self.__name = new_name  # 将new_name 赋值给 self.__name 这一步改变了值。
            else:
                print('类型不对,无法替换...')
        @name.deleter       
        def name(self):
            del self.__name     # 删除self.__name属性
    p = Person('alex')
    print(p.name)       # alex
    p.name = 'alex_sb'
    print(p.name)       # alex_sb
    del p.name
    print(p.name)  # 报错:AttributeError: 'Person' object has no attribute '_Person__name'

    @classmethod : 类方法,可以直接被类调用,不需要默认传对象参数,只需要传一个类参数就行了。

    # 全场改动折扣,不能单个改动。
    class Goods():
        __discount = 0.8    # 静态属性
        def __init__(self,name,origin_price):
            self.name = name
            self.__price = origin_price
        @property
        def price(self):
            return self.__price * Goods.__discount
        @classmethod
        def change_discount(cls,new_discount):
            cls.__discount = new_discount
    Goods.change_discount(1)        # 可以在实例化之前使用。
    g = Goods('薯片',10)
    print(g.price)

    staticmethod:

      当一个方法要使用对象的属性时,就是使用普通的方法。

      当一个方法要使用类中的静态属性时,就是用类方法。

      当一个方法要既不使用对象的属性也不使用类中的静态属性时,就可以使用 staticmethod 静态方法。

    class Student:
        def __init__(self,name):pass
        @staticmethod
        def login():    # login就是一个类中的静态方法,静态方法没有默认参数,就当成普通函数。
            pass
    
    Student.login()
  • 相关阅读:
    HttpServletRequest对象,自己学习的心得。
    @PathVariable注解的使用和@Requestparam
    微信小程序授权 获取用户的openid和session_key【后端使用java语言编写】,我写的是get方式,目的是测试能否获取到微信服务器中的数据,后期我会写上post请求方式。
    (转)ubuntu 14.04下安装hadoop2.6(伪分布式)
    数据库范式
    C与Python变量的区别
    python3获取当前目录(转)
    最大连续子数组积的线性解法
    最大子数组的线性解法
    windows7下python3.4.3 添加库路径(转)
  • 原文地址:https://www.cnblogs.com/stfei/p/8868511.html
Copyright © 2011-2022 走看看