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静态方法

原文地址:https://www.cnblogs.com/a352735549/p/8869083.html