2019-03-29-day022-封装与类方法与静态方法
昨日回顾
- 抽象类
- 规范代码,规定子类必须实现某个方法的名字
 - 不能实例化
 
 
from abc import ABCMeta, abstractmethod
class 抽象类名(metaclass=ABCMeta):
    @abstractmethod
    def open(self):
        '''这个函数要在子类中被实现'''
        pass
    @abstractmethod
    def close(self):
        '''这个函数要在子类中被实现'''
        pass
    @abstractmethod
    def read(self):
        '''这个函数要在子类中被实现'''
        pass
    @abstractmethod
    def write(self):
        '''这个函数要在子类中被实现'''
        pass
- 接口类
- 实际上多继承,继承多个抽象类,这样几个抽象类中实现的方法
 - 都必须在子类中实现
 
 - 多态
- 广义 : 一类事物表现出来的多种形态,动物可以表现成猪\狗\羊
 - 狭义 : 在函数接收参数的时候,接收的多个类的对象同属于一个父类
 - 在python中处处是多态
 
 - 鸭子类型
- 多个相似的类具有相同的方法名
 - 但是又不通过抽象类/或者继承父类约束的
 - 这几个具有相同方法的类就是鸭子类型
 - list tuple
 - 游戏里的人物
 
 
今日内容
- 封装
 - 三个装饰器
- @property
 - @classmethod
 - @staticmethod
 
 - 反射
- 最简单的对象的反射
 
 
封装
- 不想让别人改我的属性
 - 干脆不想让你看
- 用户名和密码
 
 - 广义上的封装 : 把方法和属性根据根据类别装到类中
 - 狭义上的封装 : 私有化的方法和属性
- 方法\静态变量\实例变量(对象属性)都可以私有化
 - 所谓的私有化 : 就是只能在类的内部可见,类的外部是不能访问或者查看的
 
 
class Goods:
    def __init__(self,name,price):
        self.name = name
        self.__price = price    # 私有属性
    def get_price(self):
        print(self.__price)
apple= Goods('苹果',5)
print(apple.name)
apple.get_price()
print(apple.__price)
- 私有的静态变量
 
class Role:
    __Country='China'   # 静态变量的私有化
    def func(self):
        print(self.__Country)
print(Role.__Country)  # 报错 : 因为不能再类的外部引用变量
Role().func()
- 私有的方法
 
import hashlib
class Auth:
    def __init__(self,user,pwd):
        self.username = user
        self.password = pwd
    def __md5_code(self):
        md5 = hashlib.md5(self.username.encode('utf-8'))
        md5.update(self.password.encode('utf-8'))
        return md5.hexdigest()
    def login(self):
        if self.username == 'alex' and 'ee838c58e5bb3c9e687065edd0ec454f' == self.__md5_code():
            return True
user = input('>>>')
pwd = input('>>>')
obj = Auth(user,pwd)
obj.__md5_code()   # 报错的,私有的方法不能在类的外部被使用
obj._Auth__md5_code()   # 不报错的
ret = obj.login()
if ret:
    print('登陆成功')
- 私有化是怎么完成的?
 
class Goods:
    def __init__(self,name,price):
        self.name = name
        self.__price = price    # 私有属性
    def get_price(self):
        print(self.__price)
    def set_num(self):
        self.__num = 20
apple = Goods('苹果',5)
print(apple.__dict__)
print(apple._Goods__price)   # 私有的形成
所有的私有的变化都是在类的[内部]定义的时候完成的
apple.__num = 10
print(apple.__dict__)
apple.set_num()
print(apple.__dict__)
- 私有的属性可以被继承么?
 
class Foo:
    def __init__(self):
        self.__func()
    def __func(self):
        print('in foo')
class Son(Foo):
    def __func(self):
        print('in son')
Son()
class User:
    def func(self):
        self.__wahaha()  在所有的空间里找不到 _User__wahaha
class VipUser(User):
    def __wahaha(self):
        print('in vip user')
VipUser().func()  报错
class User:
    def __wahaha(self):
        print('in user')
class VipUser(User):
    def func(self):
        self.__wahaha()
VipUser().func()    # 报错,因为在命名空间中根本不存在一个_VipUser__wahaha
#私有的这个概念 但凡在类的外面 都不能用
- 私有的所有内容 :实例变量(对象属性),静态变量(类变量),方法都不能被子类继承
 - 公有的 在类的内部外部随便用 public
 - 私有的 private 只能在类的内部使用 既不能被继承 也不能在类的外部使用
 
Property方法(使方法变为属性的调用方式)
- 私有 property 是一对好搭档
- 圆形类
 - 计算面积 计算周长
 - 半径 面积 周长
 
 
class Circle:
    def __init__(self,r):
        self.r = r
    @property  # 把装饰的一个方法伪装成一个属性
    def area(self):
        return 3.14*self.r**2
    @property
    def perimeter(self):
        return 2*3.14*self.r
c1 = Circle(5)
c1.r=10
print(c1.area)
print(c1.perimeter)
import time
class Person:
    def __init__(self,name,birth):
        self.name = name
        self.birth = birth
    @property
    def age(self):
        struct_t = time.localtime()
        age = struct_t.tm_year - int(self.birth.split('-')[0])
        return age
alex = Person('alex','1965-5-12')
print(alex.age)
Property和私有概念
一个属性 只让你看 不让你改
class Goods:
    def __init__(self,name,price):
        self.name = name
        self.__price = price
    @property
    def price(self):
        return self.__price
apple = Goods('苹果',5)
print(apple.name)
print(apple.price)
class Goods:
    discount = 0.8
    def __init__(self,name,price):
        self.name = name
        self.__price = price
    def price(self):
        return self.__price * self.discount
apple = Goods('苹果',5)
banana = Goods('香蕉',10)
print(apple.name)
print(apple.price())
print(banana.price())
Goods.discount = 1
print(apple.price())
print(banana.price())
class Goods:
    discount = 0.8
    def __init__(self, name, price):
        self.name = name
        self.__price = price
    @property
    def price(self):
        p =  self.__price * self.discount
        return p
apple = Goods('苹果', 5)
banana = Goods('香蕉', 10)
print(apple.name)
print(apple.price)
print(banana.price)
Goods.discount = 1
print(apple.price)
print(banana.price)
class Goods:
    discount = 0.8
    def __init__(self, name, price):
        self.name = name
        self.__price = price
    @property    # 只支持obj.price的方式查看这个结果,不支持修改,也不支持删除
    def price(self):
        p =  self.__price * self.discount
        return p
    @price.setter
    def price(self,value):
        self.__price = value
apple = Goods('苹果', 5)
banana = Goods('香蕉', 10)
apple.price = 8   # 对应的调用的是被setter装饰的price方法
print(apple.price)  # 对应调用的是被property装饰的price方法
class Goods:
    discount = 0.8
    def __init__(self, name, price):
        self.name = name
        self.__price = price
    @property    # 只支持obj.price的方式查看这个结果,不支持修改,也不支持删除
    def price(self):
        p =  self.__price * self.discount
        return p
    @price.setter
    def price(self,value):
        if type(value) is int or type(value) is float:
            self.__price = value
apple = Goods('苹果', 5)
banana = Goods('香蕉', 10)
apple.price = 16   # 对应的调用的是被setter装饰的price方法
print(apple.price)  # 对应调用的是被property装饰的price方法
- 如果我们定义的是普通的变量或者属性
- 那么这个属性可以从外部直接访问
 - 可以任意的修改 obj.attr = 123
 - 甚至可以删除 del obj.attr
 
 - 私有化
- 把一个属性加上双下划线 __属性名
 - 这个属性就连在外面看都看不见了
 - 我们实际上有些场景允许别人看,不许改
- __属性
 - @property装饰的属性名
 - def 属性():
 
 - 我们允许别人看,也允许别人改,但是不能瞎改,有一些要求:数据类型 范围
- __属性
 - @property装饰的属性名
 - def 属性():return __属性
 - @属性.setter
 - def 属性(self,value):
- 加点儿条件
 - 修改__属性
 
 
 
 
class Goods:
    discount = 0.8
    def __init__(self, name, price):
        self.name = name
        self.__price = price
    @property    # 只支持obj.price的方式查看这个结果,不支持修改,也不支持删除
    def price(self):
        p =  self.__price * self.discount
        return p
    @price.setter
    def price(self,value):
        if type(value) is int or type(value) is float:
            self.__price = value
    @price.deleter
    def price(self):
        del self.__price
# 想删除一个属性
apple = Goods('苹果', 5)
del apple.price
print(apple.__dict__)
apple.price
apple.price = 9
- 私有的 :通过过给__名字这样的属性或者方法加上当前所在类的前缀,把属性隐藏起来了
 - 只能在本类的内部使用,不能在类的外部使用,不能被继承
- property 把一个方法伪装成属性
 - property和私有的两个概念一起用
- 定义一个私有的
 - 再定义一个同名共有的方法,被property装饰
 
 - @方法名.setter
 - @方法名.deleter
 
 
ClassMethod类方法
class Fruits:
   __discount = 0.8
   def __init__(self, name, price):
       print('init',self)
       self.name = name
       self.__price = price
   @classmethod      # 把一个方法从对象方法,变成一个类方法
   def change_discount(cls,value):
       cls.__discount = value   # cls到底是谁??? Fruits
   @classmethod
   def get_discount(cls):
       return cls.__discount
print(Fruits.get_discount())
Fruits.change_discount(1)
print(Fruits.get_discount())
- 类方法
- 有些时候我们要修改的是类中的静态变量/类变量
 - 此时根本不会和self有任何的操作关联
 - 这时传一个self参数对我们来说完全没有用
 - 我们希望接受的是当前我们所在的类
 
 
apple = Fruits('apple',8)
apple.change_discount(0.5)
print(Fruits.get_discount())
类方法推荐使用类名调用而不是使用对象名调用
StaticMethod 静态方法
class A:
   @staticmethod  # 声明这个方法只是一个普通的不会使用任何和这个类中的变量相关的方法
   def func():    # 此时 func是一个静态方法
       print('既不操作和self相关的内容')
       print('也不操作和类名相关的内容')
A.func()
login 登录
class Student:
   def __init__(self,name):
       self.name = name
   @staticmethod
   def login():
       pass
- 先获取这个学生的用户名和密码
 - 判断他登录成功之后进行实例化
Student.login()
stu = Student('alex') 
2019-03-29-day022-封装与类方法与静态方法的更多相关文章
- 2019.03.29 读书笔记 关于override与new
		
差异:override:覆盖父类分方法,new 隐藏父类方法. 共同:都不能改变父类自身方法. public class Test { public string Name { get; set; } ...
 - 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)
		
传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...
 - 2019.03.29 NOIP训练 友好国度(点分治+容斥)
		
传送门 思路: 直接上点分治+容斥计算每个因数对应的贡献即可. 代码: #include<bits/stdc++.h> #define ri register int using name ...
 - 2019.03.29 bzoj3323: [Scoi2013]多项式的运算(非旋treap)
		
传送门 题意:定义一个无穷项的多项式f(x)f(x)f(x),初始各项系数都为0,现在有几种操作 将xLx^LxL到xRx^RxR这些项的系数乘上某个定值v 将xLx^LxL到xRx^RxR这些项的系 ...
 - 2019.03.29 读书笔记 关于params与可选参数
		
void Method1(string str, object a){} void Method2(string str, object a,object b) { } void Method3(st ...
 - Alpha冲刺(6/10)——2019.4.29
		
所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(6/10)--2019.4.29 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪 ...
 - CSharpGL(29)初步封装Texture和Framebuffer
		
+BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(29)初步封装Texture和Framebuffer +BIT祝威+悄悄在此留下版了个权的信息说: Texture和Framebuffe ...
 - 用类方法------>快速创建一个autorelease的对象,在封装的类方法内部
		
在封装的类方法内部,也就是+ (id)personWithName:(NSString *)name andAge:(int)age内部: 创建了一个person对象,并且创建了一个person*类型 ...
 - [2019.03.25]Linux中的查找
		
TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...
 - 2019.03.03 - Linux搭建go语言交叉环境
		
编译GO 1.6版本以上的需要依赖GO 1.4版本的二进制,并且需要把GOROOT_BOOTSTRAP的路径设置为1.4版本GO的根目录,这样它的bin目录就可以直接使用到1.4版本的GO 搭建go语 ...
 
随机推荐
- 『TensorFlow』第十弹_队列&多线程_道路多坎坷
			
一.基本队列: 队列有两个基本操作,对应在tf中就是enqueue&dequeue tf.FIFOQueue(2,'int32') import tensorflow as tf '''FIF ...
 - json2.js  序列化 和反序列化  转
			
http://www.cnblogs.com/youring2/archive/2013/03/01/2938850.html json2.js的源码地址: https://github.com/do ...
 - WDA基础二:界面,元素介绍
			
1.ELEMENTS: BUTTON 按钮 CAPTION 标题 DROPDOWN_BY_IDX 带序号的下拉 DROPDOWN_BY_KEY 带键值的下拉 FILE_UPLOAD ...
 - 1002. Find Common Characters查找常用字符
			
参考:https://leetcode.com/problems/find-common-characters/discuss/247573/C%2B%2B-O(n)-or-O(1)-two-vect ...
 - InnoDB存储引擎介绍-(2)redo和undo学习
			
01 – Undo LogUndo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atomi ...
 - MySql(七)多表查询
			
十一.多表查询 新建两张表:部门表(department).员工表(employee) create table department( id int, name varchar(20) ); cre ...
 - hdu多校1004 Distinct Values
			
Distinct Values Time Limit: / MS (Java/Others) Memory Limit: / K (Java/Others) Total Submission(s): ...
 - [LeetCode] 94. Binary Tree Inorder Traversal(二叉树的中序遍历) ☆☆☆
			
二叉树遍历(前序.中序.后序.层次.深度优先.广度优先遍历) 描述 解析 递归方案 很简单,先左孩子,输出根,再右孩子. 非递归方案 因为访问左孩子后要访问右孩子,所以需要栈这样的数据结构. 1.指针 ...
 - ActiveMQ 消息的重新投递
			
正常情况下:consumer 消费完消息后,会发送"标准确认"给 broker,这个确认对象以 MessageAck 类表征: // 省略其他代码.类中定义了各种确认的类型 pub ...
 - globals() 和 locals() 函数
			
globals() 和 locals() 函数 根据调用地方的不同,globals() 和 locals() 函数可被用来返回全局和局部命名空间里的名字. 如果在函数内部调用 locals(),返回的 ...