zoukankan      html  css  js  c++  java
  • Day 22 封装 property

    【封装】

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

    【好处】 

      1. 将变化隔离; 

      2. 便于使用;

      3. 提高复用性; 

      4. 提高安全性;

    【封装原则】

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

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

    私有变量和私有方法

    在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)

    # 私有的用途
    # 当一个方法不想被子类继承的时候
    # 有些属性或者方法不希望从外部被调用,只想提供给内部的方法使用
    # java中的对比
    # public 公有的    在类的内部可以使用,子类可以使用,外部可以使用    python中所有正常的名字
    # protect 保护的   在类的内部可以使用,子类可以使用,外部不可以使用  python中没有
    # private 私有的   只能在类的内部使用,子类和外部都不可以使用        python中的__名字
    
    
    # 描述一个房子
        #单价
        #面积
    class Room:
        def __init__(self,name,price,length,width,height):
            self.name = name
            self.price = price
            self.__length = length
            self.__width = width
            self.height = height
        @property
        def area(self):
            return self.__length * self.__width
    r = Room('peng',100,2,1,5)
    print(r.name)
    print(r.area)
    # 一个私有的名字,在存储的过程中仍然会出现在A.__dict__中,所以我们仍然可以调用到
    # python对其的名字进行了修改:__类名__名字
    # 只不过在类的外部调用:需要'_类名__名字'去使用
    # 在类的内部可以正常的使用名字
    class Person:
    #     def __init__(self,name,pwd):
    #         self.name = name
    #         self.__pwd(pwd)
    #     def __pwd(self,pwd):
    #         # '12345' ---> ascii ---> 2175981070935
    #         self.my_secret_pwd = 2175981070935
    # _A__N
    # 在类内 只要你的代码遇到__名字,就会被python解释器自动的转换成_类名__名字
    
    # 私有的属性
    class B:
        def __init__(self,name):
            self.__name = name
        def func(self):
            print('in func: %s'%self.__name)
    b = B('alex')
    print(b._B__name)
    b.func()
    # 私有的方法
    class C:
        def __wahaha(self):
            print('wahaha')
        def ADca(self):
            self.__wahaha()
    
    c= C()
    c._C__wahaha()
    c.ADca()
    
    
    # 在类中,静态属性,方法,对象属性都可以变成私有的,只要在这些名字之前加上__
    class D:
        def __func(self): #存储'_D__func'
            print('in func')
    
    class E(D):
        def __init__(self):
            # self.__func()   报错
            self._D__func()  #'_E__func'
    
    e = E()
    》》》in func
    #私有的名字不能被子类继承
    
    class D:
        def __init__(self):
            self.__func() #_D__func
        def __func(self):
            print('in D')
    class E(D):
        def __func(self):
            print('in E')
    
    e = E()

    》》》in D
    class D:
        def __init__(self):
            self.__func() #_D__func
        def __func(self):
            print('in D')
    class E(D):
        def _D__func(self):
            print('in E')
    
    e = E()
    >>>in E
    # 私有的名字,在类内使用的时候,就是会变形成 _该类名__方法名
    # 以此为例,没有双下划线会找到E中的func
    # 但是有了双下划线,会在调用这个名字的类D 中直接找_D__func
    class F:pass
    F.__name = 'alex' #不是在创建私有属性,只有在类的内部才关心下划线操作,变形只在类的内部发生,不会在外部发生
    print(F.__name)
    print(F.__dict__)

    alex
    {'__dict__': <attribute '__dict__' of 'F' objects>, '__module__': '__main__', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'F' objects>, '__name': 'alex'}

    class F:
        def ADCa(self):
            self.__name = 'alex'
    
    f = F()
    f.ADCa()
    # print(f.__name) #报错
    print(f._F__name) 真正工作的时候不可以这么写,只是为了应付面试

    Property

    例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
    
    成人的BMI数值:
    过轻:低于18.5
    正常:18.5-23.9
    过重:24-27
    肥胖:28-32
    非常肥胖, 高于32
      体质指数(BMI)=体重(kg)÷身高^2(m)
      EX:70kg÷(1.75×1.75)=22.86
    
    class Person:
        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
    
    kate = Person('kate',58,1.59)
    print(round(kate.BMI))
    print(round(kate.BMI))
    print(Person.__dict__)
    BMI': <property object at 0x102138958>,

    BMI 是个名词
    将一个方法伪装成一个属性
    并不会让你的代码有什么逻辑上的提高
    只是从调用者的角度上换了一种方式,使它看起来更合理
    有了property装饰,bmi不能重名,也不能重新赋值,否则会报错,说白了就是只能看了,不能修改

    @property能够将一个方法伪装成一个属性
    从原来的对象名.方法名()变成了对象名.方法名
    只是让代码变得更美观,并不会起到改变逻辑的作用
    被property装饰的bmi仍然是一个方法 存在Person.__dict__
    对象的__dict__ 中不会存储这个属性
    在一个类加载的过程中,会先加载这个中的名字,包括被property装饰
    在实例化对象的时候,python解释器会先到类的空间里看看有咩有这个被装饰的属性
    如果有就不能再在自己的空间中创建这个属性了
    
    
    # 将方法伪装成属性,方法中一般设计的就是一些计算过程
    from math import pi
    class Circle:
        def __init__(self,r):
            self.r = r
    
        @property
        def area(self):
            return pi * self.r**2
    
        @property
        def perimeter(self):
            return pi * 2* self.r
    
    p = Circle(10)
    print(round(p.area))
    print(round(p.perimeter))
    # 这样不能随意改姓名name,并且通过setname约束
    class Person:
        def __init__(self,name):
            self.__name = name #私有的属性
        @property
        def name(self):
            return self.__name
        def set_name(self,newname):
            if type(newname) is str:
                self.__name = newname
            else:
                print('您输入的姓名数据类型不合法')
    
    p = Person('alex')
    p.set_name('alex_sb')
    # p.set_name(123) 报错
    print(p.name)
    # 方法伪装成的属性的修改
    class Person:
        def __init__(self,name):
            self.__name = name #私有的属性
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self,newname):
            if type(newname) is str:
                print(newname)
            else:
                print('数据类型错误')
    
    p = Person('alex')
    print(p.name) #def name(self)
    p.name = 'SBBBBBB' #def name(self,newname):
    print(p.name) #def name(self)
    p.name  = 123
    print(p.name)
    #三个name必须一致

    alex
    SBBBBBB
    alex

    数据类型错误

    
    
    #方法伪装成属性的删除
    class Person:
        def __init__(self,name):
            self.__name = name
    
        @property
        def name(self):
            return self.__name
        @name.deleter
        def name(self):
            print('name 被删除')
    
        # @name.deleter
        # def name(self):
        #     del self.__name #这个可以真正删除
    
    p = Person('egon')
    print(p.name)
    del p.name #只相当于执行了被@name.deleter这个函数,并没有真正删除
    print(p.name)
    # @property--->func 将方法伪装成属性,只是看的事儿
    # @func.setter ---->func 让伪装的属性进行赋值的时候用这个方法
    # @func.deleter --->func 在执行del对象,func的时候调用这个方法,一般情况不用
    
    
    # 商品的折扣
    # 想看折后价格
    class Goods:
    def __init__(self,name,price,discount):
            self.name = name
            self.__price = price
            self.__discount = discount
    
        @property
        def price(self):
            return self.__price *self.__discount
        @price.setter
        def price(self,new_price):
            if type(new_price) is int or type(new_price) is float:
                self.__price = new_price
            else:
                print('您输入的数据类型错误')
    
    apple = Goods('apple',5,0.8)
    print(apple.price)
    #  修改苹果价格
    apple.price = 8
    print(apple.price)
    店庆全场八折# 折扣结束 折扣变了 恢复折扣
    class Product:
        __discount = 0.8
        def __init__(self,name,price):
            self.name = name
            self.__price = price
    
        @property
        def price(self):
            return self.__price * Product.__discount
    
        @classmethod #不依赖对象的方法,就应该定义为类方法,类方法可以任意的操作类中的静态变量
        def change_discount(cls,new_discount): # 类方法,可以直接被类调用,不需要默认传对象参数,只需要传一个类参数就可以了
            cls.__discount = new_discount
    
    Product.change_discount(1)
    apple = Product('apple',5)
    banana = Product('banana',8)
    print(apple.price)
    print(banana.price)
    #使用什么样的方法要看具体用到了哪些名称空间中的值
    # 当一个方法要使用对象的属性时,就使用普通的方法
    # 当一个方法要使用类中的静态属性时,就使用类方法
    # 当一个方法既不使用对象的属性也不使用类中的静态属性时,就可以使用staticmethod静态方法

    # def login():
    #     user= input('user :')
    #     if user == 'alex':print('success')
    #     else :print('faild')
    #
    # login()
    class Student:
        def __init__(self,name):pass
    
        @staticmethod
        def login(a):                   # login就是一个类中的静态方法 静态方法没有默认参数 就当成普通的函数使用即可
            user = input('user :')
            if user == 'alex':
                print('success')
            else:
                print('faild')
    
    Student.login(1)
    class A:
        __role = 'CHINA'
        @classmethod
        def show_role(cls):
            print(cls.__role)
    
        @staticmethod
        def get_role():
            return A.__role
    
        @property
        def role(self):
            return self.__role
    
    a = A()
    print(a.role)
    print(a.get_role())
    a.show_role()

    CHINA
    CHINA
    CHINA





  • 相关阅读:
    springcloud-04-自定义ribbon的配置方式
    springcloud-03-服务注册
    springcloud-02-eureka
    springcloud-01-介绍
    使用jdk生成ssl证书文件
    CentOS7忘记root密码的修改方法
    2.1 Scala语言概述
    1.大数据技术概述
    KL散度=交叉熵-熵
    7.数据结构---图(遍历)
  • 原文地址:https://www.cnblogs.com/kateli/p/8867670.html
Copyright © 2011-2022 走看看