昨日回顾

  • 抽象类

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

    1.树的层序遍历 使用两个List 数组 或者 两个queue队列,交替进行,将遍历到的一层放在第一个里面,之后再将遍历到的第二层放在第二个里面. 2.将一个无符号整数的二进制表示形式逆向输出 需要将 ...

  2. python--model进阶

    一.QuerySet 1.可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句.  >>> Entry.objects.a ...

  3. SQL Server 创建触发器(trigger)

    update 触发器: if(OBJECT_ID('trigger_compost_up') is not null) drop trigger trigger_compost_up go creat ...

  4. Redis+Twemproxy+HAProxy集群(转) 干货

    原文地址:Redis+Twemproxy+HAProxy集群  干货 Redis主从模式 Redis数据库与传统数据库属于并行关系,也就是说传统的关系型数据库保存的是结构化数据,而Redis保存的是一 ...

  5. noip2014生活大爆炸版石头剪刀布

    题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一 样,则不分胜负.在<生活大爆炸>第二季第8集中出现了一种石头剪刀布的升级版游戏. 升级版游戏在传统的 ...

  6. Git clone 常见用法

    二 克隆Git仓库     1.1 从远程仓库中克隆整个代码仓库 mkdir Demo //在当前路径下新建一个文件夹,用来存放将要拉取的整个代码库 cd Demo           //进入这个文 ...

  7. maven打包上传到本地中央库

    pom文件中添加插件如下 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins< ...

  8. python xlrd使用

    python xlrd使用 1● xlrd安装   管理员模式           success 2● 引用 import xlrd    

  9. HTTP、TCP、UDP的区别

    TCP.UDP的区别 1.TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接 2.TCP提供可靠的服务.也就是说,通过TCP连接传送的数据,无差错,不丢失,不重 ...

  10. Laravel 更新数据时在表单请求验证中排除自己,检查指定字段唯一性

    原文地址:https://moell.cn/article/24 不错的laravel网站 需求场景 修改用户信息时,在表单请求验证中排除当前邮箱所在的记录行,并检查邮箱的唯一性. Laravel版本 ...