昨日回顾

  • 抽象类

    • 规范代码,规定子类必须实现某个方法的名字
    • 不能实例化
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())
  • 类方法

    1. 有些时候我们要修改的是类中的静态变量/类变量
    2. 此时根本不会和self有任何的操作关联
    3. 这时传一个self参数对我们来说完全没有用
    4. 我们希望接受的是当前我们所在的类
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-封装与类方法与静态方法的更多相关文章

  1. 2019.03.29 读书笔记 关于override与new

    差异:override:覆盖父类分方法,new 隐藏父类方法. 共同:都不能改变父类自身方法. public class Test { public string Name { get; set; } ...

  2. 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)

    传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...

  3. 2019.03.29 NOIP训练 友好国度(点分治+容斥)

    传送门 思路: 直接上点分治+容斥计算每个因数对应的贡献即可. 代码: #include<bits/stdc++.h> #define ri register int using name ...

  4. 2019.03.29 bzoj3323: [Scoi2013]多项式的运算(非旋treap)

    传送门 题意:定义一个无穷项的多项式f(x)f(x)f(x),初始各项系数都为0,现在有几种操作 将xLx^LxL到xRx^RxR这些项的系数乘上某个定值v 将xLx^LxL到xRx^RxR这些项的系 ...

  5. 2019.03.29 读书笔记 关于params与可选参数

    void Method1(string str, object a){} void Method2(string str, object a,object b) { } void Method3(st ...

  6. Alpha冲刺(6/10)——2019.4.29

    所属课程 软件工程1916|W(福州大学) 作业要求 Alpha冲刺(6/10)--2019.4.29 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪 ...

  7. CSharpGL(29)初步封装Texture和Framebuffer

    +BIT祝威+悄悄在此留下版了个权的信息说: CSharpGL(29)初步封装Texture和Framebuffer +BIT祝威+悄悄在此留下版了个权的信息说: Texture和Framebuffe ...

  8. 用类方法------>快速创建一个autorelease的对象,在封装的类方法内部

    在封装的类方法内部,也就是+ (id)personWithName:(NSString *)name andAge:(int)age内部: 创建了一个person对象,并且创建了一个person*类型 ...

  9. [2019.03.25]Linux中的查找

    TMUX天下第一 全世界所有用CLI Linux的人都应该用TMUX,我爱它! ======================== 以下是正文 ======================== Linu ...

  10. 2019.03.03 - Linux搭建go语言交叉环境

    编译GO 1.6版本以上的需要依赖GO 1.4版本的二进制,并且需要把GOROOT_BOOTSTRAP的路径设置为1.4版本GO的根目录,这样它的bin目录就可以直接使用到1.4版本的GO 搭建go语 ...

随机推荐

  1. 标准化数据-StandardScaler

    StandardScaler----计算训练集的平均值和标准差,以便测试数据集使用相同的变换 官方文档: class sklearn.preprocessing.StandardScaler(copy ...

  2. 【IDEA】【3】操作使用

    前言: 1,显示工具栏及底部周边工具栏 2,修改项目名称 3,文件重命名 4,鼠标移动到方法上时进行提示注释 5,修改文件后自动重启 6,查看代码覆盖率 正文: 1,显示工具栏及底部周边工具栏 Vie ...

  3. 关于react16.4——转发refs和片段Fragment

    1.转发refs Ref 转发是一种自动将 ref 通过组件传递给子组件的技术. 一些组件倾向于以与常规 DOM button 和 input 类似的方式在整个应用程序中使用, 并且访问他们的 DOM ...

  4. seaweedFS

    那首先我们来分析一下seaweedfs是什么?seaweedfs是一个非常优秀的由 golang 开发的分布式存储开源项目.它是用来存储文件的系统,并且与使用的语言无关,使得文件储存在云端变得非常方便 ...

  5. js动态检测加载 JQ

    var jqcdnurl = 'https://cdn.bootcss.com/jquery/3.2.1/jquery.js'; //控制台输出 function log() { for (var i ...

  6. MSMQ 概述

    MSMQ 概述 1) MSMQ概述 MSMQ 表示微软消息队列服务.MSMQ 可以工作在在线或者离线场景,并提供异步编程功能.如果客户端离线,MSMQ将会是最合适的方法,这是因为服务端不需要等待客户端 ...

  7. vue购物车功能源码

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  8. PyCharm+Scrapy爬取安居客楼盘信息

    一.说明 1.1 开发环境说明 开发环境--PyCharm 爬虫框架--Scrapy 开发语言--Python 3.6 安装第三方库--Scrapy.pymysql.matplotlib 数据库--M ...

  9. Linux查看用户属于哪些组/查看用户组下有哪些用户

    一.关于/etc/group格式的讨论 在说/etc/group格式的时候,网上很多文章都会说是“组名:组密码:组ID:组下用户列表”,这说法对了解/etc/group格式是没问题的,但如果碰到“查看 ...

  10. java 常用命令

    #查看堆使用情况jmap -heap [pid]#查看占用内存高的对象jmap -histo:live [pid] | head -n 100#查看占用内存高的对象,dump成文件,线下分析jmap ...