zoukankan      html  css  js  c++  java
  • Day22

    1、封装

    面向对象的三大特性 : 继承 多态 封装
    封装 :
    广义上的
    狭义上的 :会对一种现象起一个专门属于它的名字
    把一堆东西装在一个容器里
    函数和属性装到了一个非全局的命名空间 —— 封装
    class A:
    __N = 'aaa' # 静态变量
    print(A.__N)
    python
    pulic 公有的
    private 私有的

    java完全面向对象的语言
    public 公有的
    protect 保护的
    private 私有的

    定义一个私有的名字 : 就是在私有的名字前面加两条下划线 __N = 'aaa'

    所谓私有,就是不能在类的外面去引用它

    class A:
        __N = 'aaa'  # 静态变量
        def func(self):
            print(A.__N)  # 在类的内部使用正常
    
    a = A()
    a.func()
    print(A.__N)   # 在类的外部直接使用 报错
    View Code
    class A:
        __N = 'aaa'  # 静态变量
        def func(self):
            print(A.__N)  # 在类的内部使用正常
    
    print(A.__dict__)
    print(A._A__N)   # python就是把__名字当成私有的语法
    View Code

    一个私有的名字 在存储的过程中仍然会出现在A.__dict__中,所以我们仍然可以调用到

    python对其的名字进行了修改:_类名__名字

    只不过在类的外部调用:需要''_类名_名字''去使用

    在类的内部可以正常的使用名字

    在类内 只要你的代码遇到__名字,就会被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()     #报错  私有的名字不能被子类继承
    View Code
    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
    View Code
    class F:pass
    F.__name = 'alex'  # 不是在创建私有属性
    print(F.__name)
    print(F.__dict__)
    #变形只在类的内部发生
    View Code

    java中的对比

    public 公有的  在类的内部可以使用,子类可以使用,外部可以使用  python中所有正常

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

    private 私有的  只能在类的内部使用,子类和外部都不可以使用  python中的__名字

    私有的用法

    当一个方法不想被子类继承的时候 有些属性或者方法不希望从外部被调用,只想提供给内部的方法使用

    2、property方法

    class Person:
        def __init__(self,name,weight,height):
            self.name = name
            self.__height = height
            self.__weight = weight
            # self.bmi = self.__weight / self.__height ** 2
            # self.bmi = self.cal_BMI()
    
        def cal_BMI(self):
            return self.__weight / self.__height ** 2
    
        @property
        def bmi(self):
            return self.__weight / self.__height ** 2
    p = Person('大表哥',92,1.85)
    # print(p.cal_BMI())
    # p.cal_BMI()   # bmi是一个名词
    print(p.bmi)   # bmi是一个名词
    p._Person__weight = 90
    print(p.bmi)
    View Code

    @property 能够将一个方法伪装成一个属性

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

      并不会让代码有什么逻辑上的提高

      只是从调用者的角度上换了一种方式,使之看起来更合理

    # 如果有重名的名字
    class Person:
        def __init__(self,name,weight,height):
            self.name = name
            self.__height = height
            self.__weight = weight
            #self.bmi=111
        @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解释器会先到类的空间里看看有没有这个被装饰的属性,
    # 如果有就不能再在自己对象的空间中创建这个属性了
    View Code
    #方法伪装成的属性的修改
    class Person:
        def __init__(self,n):
            self.__name=n
        @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)    #def name(self)
    p.name='wusir'    #def name(self,new_name)
    print(p.name    )#def name(self)
    View Code
    #方法伪装成的属性的删除
    class Person:
        def __init__(self,n):
            self.__name = n  # 私有的属性了
        @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)
    View Code

    @property -->func 将方法伪装成属性,只观看的事儿

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

    @func.deleter -->func 在执行del 对象.func的时候调用这个方法 一般情况下用来做删除 基本不用

    # 商品的 折扣
    # 有一个商品 : 原价 折扣
    # 当我要查看价格的时候 我想看折后价
    class Goods:
        def __init__(self,name,origin_price,discount):
            self.name = name
            self.__price = origin_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
    apple = Goods('apple',5,0.8)
    print(apple.price)
    # 修改苹果的原价
    apple.price = 8
    print(apple.price)
    View Code

    将一些需要随着一部分属性的变化而变化的值的计算过程 从方法 伪装成属性
    将私有的属性保护起来,让修改的部分增加一些约束,来提高程序的稳定性和数据的安全性

    3、classmethod和staticmethod

    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)    #不依赖对象的方法 就应该定义成类方法 类方法可以任意的操作类中的静态变量
    apple=Goods('apple',5)
    banana=Goods('banana',8)
    print(apple.price)
    View Code

    staticmethod

    class Studeng:
        def __init__(self,name):pass
        @staticmethod
        def login(a):
            user=input('user:')
            if user =='alex':
                print('success')
            else:
                print('faild')
    Student.login(1)
    View Code

    完全面向对象编程

    先登录后实例化

    还没有一个具体的对象的时候 就要执行login方法

    使用什么样的方法要看具体用到了哪些名称空间中变量

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

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

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

  • 相关阅读:
    [HDU6146]Pokémon GO
    [BZOJ1406]密码箱
    [BZOJ1045]糖果传递
    [Codeforces613E]Puzzle Lover
    [Codeforces778E]Selling Numbers
    [Codeforces477D]Dreamoon and Binary
    [Codeforces440D]Berland Federalization
    [Codeforces441E]Valera and Number
    文件上传漏洞(绕过姿势)
    WebShell代码分析溯源(第1题)墨者学院
  • 原文地址:https://www.cnblogs.com/a352735549/p/8869083.html
Copyright © 2011-2022 走看看