day 22 封装 + property + classmethod + staticmethod

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

封装:()

  广义上的:

  狭义上的:会为一种现象起一个专属它的名字

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

class A:

  __N = 'aaa'  静态变量

print(A.__N)

 

python

1.public

2.private

 

java(完全是面向对象的语言)

1.public

2.protect

3.private

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

所谓私有就是不能再类的外面引用它

 

 class A:
# __N = 'aaa' # 静态变量
# def func(self):
# print(A.__N) # 在类的内部使用正常
#
# a = A()
# a.func()
# print(A.__N) # 在类的外部直接使用 报错

class A:
__N = 'aaa'
def func(self):
print(A.__N)

print(A.__dict__)
print(A._A__N)

#{'func': <function A.func at 0x0000011B197637B8>, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '_A__N': 'aaa', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'A' objects>}
#aaa



# 一个私有的名字 在存储的过程中仍然会出现在A.__dict__中,所以我们仍然可以调用到。
# python对其的名字进行了修改: _类名__名字
# 只不过在类的外部调用 :需要“_类名__名字”去使用
# 在类的内部可以正常的使用名字
 _A__N
# 在类内 只要你的代码遇到__名字,就会被python解释器自动的转换成_类名__名字



# 私有的名字,在类内使用的时候,就是会变形成_该类名__方法名
# 以此为例 :没有双下换线会先找E中的func
# 但是有了双下划线,会在调用这个名字的类D中直接找_D__func
# 变形只在类的内部发生

# class D:
#     def __init__(self):
#         self.__func()
#     def __func(self):
#         print('in D')
#
# class E(D):
#     def __func(self):
#         print('in E')
# e = E()

# class F:pass
# print(F.__dict__)
# F.__name = 'aaa'
# f = F()
# print(f.__name)
# print(F.__dict__)
 

# class F:pass
# print(F.__dict__)
# F.__name = 'aaa'
# f = F()
# print(f.__name)
# print(F.__dict__)
# class F:
#     def ADC(self):
#         self.__name = 'alex'
#
# f = F()
# f.ADC()
# print(F.__dict__)
# print(f.__dict__)

这个实例说明:在对象中创建的静态属性

 

Java中的对比:

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

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

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

 

私有的用法:

  当一个方法不想被子类继承的时候:

  有些属性和方法不希望从外部调用,只希望从内部调用

# 人体BMI指数
# 体质指数(BMI)=体重(kg)÷身高^2(m)
# 写一个类 描述人体BMI指数

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)
# 将一个方法伪装成一个属性
# 并不会让你的代码有什么逻辑上的提高
# 只是从调用者的角度上换了一种方式,使之看起来更合理
# @property 能够将一个方法伪装成一个属性
# 从原来的的对象名.方法名(),变成了对象名.方法名
# 只是让代码变的更美观

注意:如果出现了重名的名字:程序就会报错



# 将方法伪装成属性,方法中一般涉及的都是一些计算过程
# from math import pi
# class Circle:
#     def __init__(self,r):
#         self.r = r
#     @property
#     def area(self):
#         return self.r**2*pi
#
#     @property
#     def perimeter(self):
#         return 2*pi*self.r
# c = Circle(10)
# print(c.area)
# print(c.perimeter)
# c.r = 15
# print(c.area)
# print(c.perimeter)

因为property不能传参,所有如果还想要将动态函数名改为名词性函数名,就需要用到名词性函数名.settle

 方法伪装成的属性的修改
# 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 = 'alex_sb' #def name(self,new_name):
# print(p.name)       #def name(self):
# p.name = 123 #def name(self,new_name):
# print(p.name)       #def name(self):

 


# 方法伪装成的属性的删除
class Person:
def __init__(self,n):
self.__name = n # 私有的属性了
@property # 重要程度 ****
def name(self):
return self.__name
# @name.deleter
# def name(self):
# print('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,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)


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)
print(banana.price)

# 折扣变了 店庆结束 恢复折扣
# apple.change_discount(1) # 如果要改变折扣 是全场的事情 不牵扯到一个具体的物品 所以不应该使用对象来调用这个方法
# print(apple.price)
# print(banana.price)


# staticmethod
# 当一个方法要使用对象的属性时 就是用普通的方法
# 当一个方法要使用类中的静态属性时 就是用类方法
# 当一个方法要既不使用对象的属性也不使用类中的静态属性时,就可以使用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)

# 完全面向对象编程
# 先登录 后 实例化
# 还没有一个具体的对象的时候 就要执行login方法

# 使用什么样的方法要看具体用到了哪些名称空间中的变量
# 当一个方法要使用对象的属性时 就是用普通的方法
# 当一个方法要使用类中的静态属性时 就是用类方法
# 当一个方法要既不使用对象的属性也不使用类中的静态属性时,就可以使用staticmethod静态方法
 
 

 



 



 

posted @ 2018-04-17 19:23  Coca-Mirinda  阅读(227)  评论(0编辑  收藏  举报