zoukankan      html  css  js  c++  java
  • 0417 封装 property、classmethod、staricmethod

    一、封装

    把一堆东西装在一个容器里  函数和属性装到了一个非全局的命名空间
    class A:
        __N = 123   # 静态变量
        def func(self):
            print(A.__N)   # 在类的内部使用正常
    a=A()
    a.func()
    print(A.__N) # 在类的外部直接使用 报错
    print(A._A__N)   # python就是把__名字当成私有的语法
    定义一个私有的名字 : 就是在私有的名气前面加两条下划线 __N =123
    所谓私有,就是不能在类的外面去引用它
    一个私有的名字 在存储的过程中仍然会出现在A.__dict__中,所以我们仍然可以调用到。
    python对其的名字进行了修改: _类名__名字
    只不过在类的外部调用 :需要“_类名__名字”去使用
    在类的内部可以正常的使用名字
    
    
    _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() # '_E__func'
    e = E() # 会报错
    私有的名字不能被子类继承

    class D:
    def __init__(self):
    self.__func()
    def __func(self):
    print('in D')

    class E(D):
    def __func(self):
    print('in E')
    e = E() 'in D'
    私有的名字,在类内使用的时候,就是会变形成_该类名__方法名
    以此为例 :没有双下换线会先找E中的func
    但是有了双下划线,会在调用这个名字的类D中直接找_D__func
    
    
    class F:
        pass
    F.__name = 'alex'  # 不是在创建私有属性
    print(F.__name)
    print(F.__dict__)
    变形只在类的内部发生
    
    class F:
        def ADCa(self):
            self.__name = 'alex'   # _F__name
    f = F()
    f.ADCa()
    print(f._F__name)
    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

    def area(self):
    return self.__length*self.__width

    r = Room('鹏鹏',100,2,1,0.5)
    print(r.name)
    print(r.price)
    print(r.area()) # 查长宽高就报错

    二、property

    人体BMI指数
    体质指数(BMI)=体重(kg)÷身高^2(m)
    写一个类 描述人体BMI指数
    class Person:
    def __init__(self,name,gao,zhong):
    self.name = name
    self.__gao = gao
    self.__zhong = zhong
       @property
    def BMI(self):
    return self.__zhong / self.__gao**2
    a=Person('zx',170,80)
    print(a.BMI)
    将一个方法伪装成一个属性
    并不会让你的代码有什么逻辑上的提高
    只是从调用者的角度上换了一种方式,使之看起来更合理
    @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('大表哥',92,1.85)
    print(p.__dict__)
    print(p.bmi) # 对这个属性 只能看了

    被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 perimter(self):
    return 2*pi*self.r
    a=Circle(10)
    print(a.area)
    print(a.perimter)
    c.r = 15  #改变属性,给属性重新赋值
    print(c.area)
    print(c.perimeter

    方法伪装成的属性的修改
    class Person:
    def __init__(self,name):
    self.__name = name
    @property
    def name(self):
    return self.__name
    @name.setter
    def name(self,new_name):
    if type(new_name) is str:
    self.__name = new_name
    else:
    print('输入有误')
    p = Person('alex')
    print(p.name) alex
    p.name = 'sb'
    print(p.name) sb
    p.name = 123 输入有误
    方法伪装成的属性的删除
     class Person:
        def __init__(self,name):
    self.__name = name
    @property
    def name(self):
    return self.__name
    @name.deleter
    def name(self):
    del self.__name
    p = Person('alex')
    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,orinig_price,discount):
    self.name = name
    self.__orinig_price = orinig_price
    self.__discount = discount
    @property
    def price(self):
    return self.__orinig_price * self.__discount
    @price.setter
    def price(self,new_price):
    self.__orinig_price = new_price
    a = Goods('橙子',10,0.8)
    print(a.price)
    a.price = 20
    print(a.price)
    property的两个作用:
    将一些需要随着一部分属性的变化而变化的值的计算过程 从方法 伪装成属性
    将私有的属性保护起来,让修改的部分增加一些约束,来提高程序的稳定性和数据的安全性

    三、classmethod与staricmethod

    不借助对象改变静态变量
    class
    Goods: __discount = 0.8 def __init__(self, name, orinig_price, ): self.name = name self.__orinig_price = orinig_price @property def price(self): return self.__orinig_price * Goods.__discount @classmethod def change_discount(cls,new_price): 类方法 可以直接被类调用 不需要默认传对象参数 只需要传一个类参数就可以了 cls.__discount = new_price Goods.change_discount(1) 不依赖对象的方法 就应该定义成类方法 类方法可以任意的操作类中的静态变量 a = Goods('橙子',10) print(a.price)
    
    
    staticmethod
    使用什么样的方法要看具体用到了哪些名称空间中的变量
      当一个方法要使用对象的属性时 就使用普通的方法
      当一个方法要使用类中的静态属性时 就使用类方法
      当一个方法既不使用对象的属性也不使用类中的静态属性时,就可以使用staticmethod静态方法

    class
    Student: def __init__(selfn,name):pass @staticmethod def login(): login就是一个类中的静态方法 静态方法没有默认参数 就当成普通的函数使用即可 user = input('user') if user == 'alex' print('ok') else: print('bad') Student.login()
    使用什么样的方法要看具体用到了哪些名称空间中的变量完全面向对象编程
    先登录 后 实例化
    还没有一个具体的对象的时候 就要执行login方法
  • 相关阅读:
    openstack 相关服务常用命令整理
    openstack(Pike 版)集群部署(六)--- Horizon 部署
    node express4.x 的安装
    jquery mobile 笔记
    multi-node和generic-pool两大利器
    ADT eclipse的几个快捷键
    安卓入门笔记
    HTML颜色代码表
    [转载]Delphi常用类型及定义单元
    简化连接Buffer对象的过程
  • 原文地址:https://www.cnblogs.com/Mr-Murray/p/8870009.html
Copyright © 2011-2022 走看看