1,封装

## 什么是封装 what 

对外隐藏内部的属性,以及实现细节,并给外部提供使用的接口
学习封装的目的:就是为了能够限制外界对内部数据的方法
注意 :封装有隐藏的意思,但不是单纯的隐藏 python 中属性的权限分为两种:  
  1,分开的
    没有任何限制,谁都可以访问
  2,私有的
    只有当前类本身能够访问
  默认为公共的 ##如何封装 how 为什么要封装:   1,提高安全性 (封装属性)
       
  2,隔离复杂度  (封装方法)     
一个类中分为两种数据,属性和方法:
封装属性:

class Student:

    def __init__(self,name,age,gender,id_card):
self.name = name
self.age = age
self.gender = gender
self.__id_card = id_card def show_id_card(self):
# 可以在这里添加额外的任何逻辑代码 来限制外部的访问 #在类的内部 可以访问
print(self.__id_card)
对私有属性的访问以及修改:

class Student:
def __init__(self,name,age,gender,id_card):
self.name = name
self.age = age
self.gender = gender
self.__id_card = id_card #访问器
def get_id_card(self,pwd):
#可以在这里添加额外的任何逻辑代码,来限制外部的访问
#在类的内部,可以访问
if pwd == '':
return self.__id_card
raise Exception('密码错误!') #修改被封装的属性,称之为设置器
def set_id_card(self,new_id):
#身份证必须是字符串类型
#长度必须是18位
if isinstance(new_id,str) and len(new_id) == 18:
self.__id_card = new_id
else:
raise Exception('身份证号码必须是字符串,且长度为18') s = Student('rose',10,'man','')
print(s.get_id_card('')) #
#设置属性
s.set_id_card('')
print(s.get_id_card('')) #222222222222222222
什么样的方法应该被封装起来 :
  当这个对象存在一个机密性的属性 例如 人的身份证 银行卡密码等等,这样属性不应该被外界直接 访问当 ,那就封装起来。
​ 一个为内部提供支持的方法,不应该让外界直接访问,那就封装起来 ,如下例中的 user_auth等...

class ATM:
#提供给外部访问的一个接口
def withdraw(self):
#输入账号和密码
self.__user_auth()
#输入取款金额
self.__input_money()
#保存记录
self.__save_record() #封装内部的实现细节
def __user_auth(self):
print('输入账号和密码') def __input_money(self):
print('输入取款金额') def __save_record(self):
print('记录流水') a = ATM()
a.withdraw()

  #输入账号和密码
  #输入取款金额
  #记录流水

 

2,封装的原理:

'''
python 是通过变形的方式来实现的封装
如何变形 : 在名称带有双下划线开头的变量名字前添加_类名 如:_Person_id_card
当然通过变形后的名字可以直接访问被隐藏的属性 ,但通常不这样做 如: p._Person__id_card
变形仅在类的定义阶段发生一次,后续再添加在带有双下划线的任何属性都不会变形,就是普通函数
''''' class Person:
def __init__(self,name,age,id_card):
self.name = name
self.age = age
self.__id_card = id_card #_Person__id_card def get_id_card(self):
return self.__id_card p = Person('rose',20,'')
print(p.__dict__) #{'name': 'rose', 'age': 20, '_Person__id_card': '12321323123123'}
print(p.name) p.__id_card = '' #重新开辟了一块空间存储
print(p.__dict__) #{'name': 'rose', 'age': 20, '_Person__id_card': '12321323123123', '__id_card': '123'} print(p._Person__id_card) #直接强制访问 12321323123123 p.__gender = 'man'
print(p.__dict__) #{'name': 'rose', 'age': 20, '_Person__id_card': '12321323123123', '__id_card': '123', '__gender': 'man'}

3,Property ,setter ,deleter

Property 作用 : 将一个方法伪装成普通属性 

为什么用 property  : 希望将访问私有属性和普通属性的方式变得一致

与property相关的两个装饰器: 

  setter : 用点语法 给属性赋值时触发   

  deleter: 用点语法删除属性时触发 

class Teacher:
def __init__(self,name,age,salary):
self.name = name
self.age = age
self.__salary = salary @property   #getter 用于访问私有属性的值,也可以访问普通属性
def salary(self):
return self.__salary @salary.setter #用于设置私有属性的值,也可以设置普通属性
def salary(self,new_salary):
self.__salary = new_salary @salary.deleter #用于设置私有属性的,也可以删除普通属性
def salary(self):
print(self.__dict__) #{'name': 'owen', 'age': 29, '_Teacher__salary': 88888}
del self.__dict__['_Teacher__salary'] t = Teacher('owen',29,88888)
# del t.salary print(t.salary) # t.salary = 100000
print(t.salary) # '''
总结:
被封装的属性在访问时,需要调用方法,而普通属性直接点就OK,这样一来对于对象的使用者而言
必须知道要访问的属性,是私有还是公开,然后在调用对应的方法.用起来就会比较麻烦
此时,我们的目的就是让访问私有属性和访问普通属性的方式一样通过点来调用   property装饰器:就是用来将一个方法伪装成属性,可以直接通过点来调用
'''
'''
property的另一种使用场景,计算属性 什么是计算属性:
一个属性它的值不是固定死的,而是通过计算产生的 ''''' class Person:
def __init__(self,name,height,weight):
self.name = name
self.height = height
self.weight = weight
# self.BMI = weight /(height**2) @property
def BMI(self):
return self.weight/(self.height**2) @BMI.setter
def BMI(self,new_BMI):
print('BMI 不支持自定义.....') p = Person('owen',1.78,60)
print(p.BMI) #18.93700290367378 p.weight = 90
print(p.BMI) #28.40550435551067 #被封装的内容(私有的) 不可以被继承
class A:
__name = 'rose' #变形后 _A__name def __say_hi(self):
print('A say hi') class B(A):
def test(self):
# print(super().__name) #变形后 _B__name 在哪个类就以哪个类变形
print(A._A__name) #通过super()不能使用父类的私有属性,可以通过类名直接访问
b = B()
b.test()

4,多态

"""
多态 :
多态不是一个具体的技术 或代码
指的是 多个不同类型对象 可以响应同一个方法 ,产生不同结果 某种事物具备多个不同形态
例如 水: 气态 固态 液态
动物: 人 猫 猪
汽车人: 汽车 飞机 人型 OOP中 标准解释: 多个不同类型对象 可以响应同一个方法 并且产生不同结果 多态的带来的好处:
只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的,以不变应万变 ,提高了灵活性
提高扩展性 如何实现多态:
鸭子类型 就是典型的多态 多种不同类型 使用方法一样 """ # import abc
# class Animal(metaclass=abc.ABCMeta):
#
# @abc.abstractmethod
# def bark(self):
# pass
#
# @abc.abstractmethod
# def run(self):
# pass
#
# @abc.abstractmethod
# def sleep(self):
# pass class Person(): def bark(self):
print("Hello!") def run(self):
print("两条腿跑!") def sleep(self):
print("躺着睡!") class Cat(): def bark(self):
print("喵喵喵") def run(self):
print("四条腿跑!") def sleep(self):
print("趴着睡!") class Pig():
def bark(self):
print("哼哼哼!") def run(self):
print("四条腿跑!") def sleep(self):
print("侧躺着睡!") person1 = Person()
cat1 = Cat()
pig1 = Pig() person1.sleep()
cat1.sleep()
pig1.sleep() # 如果没有多态 需要分别学习 person cat pig 的不同使用方法 这对于使用者而言太麻烦了 # 一个用来管理动物的方法 只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型
def management_animal(animal):
print("==================正在溜%s=============" % animal.__class__.__name__)
animal.bark()
animal.run()
animal.sleep() # 来了一堆动物
person1 = Person()
cat1 = Cat()
pig1 = Pig() management_animal(person1)
management_animal(cat1)
management_animal(pig1) class Dog():
def bark(self):
print("汪汪汪...") def run(self):
print("四条腿跑!") def sleep(self):
print("趴着睡!") dog1 = Dog()
management_animal(dog1) class Fish():
def bark(self):
print("超声波...") def run(self):
print("游来游去.....") def sleep(self):
print("睁眼睡觉....") f = Fish()
management_animal(f) # 无处不在的多态 # def MY_LEN(obj):
# return obj.__len__()
#
# print(MY_LEN("abcdefg"))
# print(MY_LEN([1,2,3,4]))
# print(MY_LEN({"name":123})) print(len(""))

5,常用的内置函数 ,__str__ , __del__

__str__ :

'''
类中的__str__:
该方法在object中有定义,默认行为,返回对象类型以及地址
在将对象转为字符串时执行
注意:返回值必须为字符串类型
子类可以覆盖该方法来完成,对打印内容的自定义
''''' class Person:
def __init__(self,name,age):
self.name = name
self.age = age #将对象转换为字符串时执行
def __str__(self):
print('str run')
return 'my name is %s.age is %s'%(self.name,self.age) p = Person('rose',20) '''#在打印前都会先将要打印的内容转为字符串,通过调用__str__函数'''
print(p) #my name is rose.age is 20 str(p) #str run
'''
__del__:
当对象被删除前会自动调用该方法
声明的时候会删除对象?
1,程序运行结束,解释器退出,将自动删除所有数据
2,手动调用del 时也会删除对象 注意: 该函数不是用来删除对象的 使用场景:
当你的对象在创建时,开启了不属于解释器的资源 ,例如: 打开了一个文件
必须保证当前对象被删除时,同时关闭额外的资源,如:文件 也称之为析构函数(一个个拆分,解析) 构造 的反义词
构造:指的是从无到有
析构:指的是有到无
简单的说就对象所有数据全部删除 总结:__del__该函数 用于在对象删除前做的一些清理操作(或提醒)
''''' #假设要求每一个person对象都要绑定一个文件
class Person:
def __init__(self,name,path):
self.name = name
self.file = open(path,encoding='utf-8') #读取数据的方法
def read_data(self):
return self.file.read() def __del__(self):
print('del run1') #当程序执行完后才会执行这个
self.file.close() p = Person('owen','封装方法.py')
print(p.read_data())

6,反射

英文中叫反省 (自省)   

面向对象中的反省 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力;   

一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性 

## 反射就是通过字符串来操作对象属性

涉及到的方法:
hasattr   判断是否存在某个属性 getattr 获取某个属性的值 setattr 新增或修改某个属性 delattr   删除某个属性 案例1:
import os class Student:
def __init__(self,name):
self.name = name
def www(self):
print('') stu = Student('rose') #反射的四个方法
print(hasattr(stu,'name')) #True
print(getattr(stu,'name')) #rose setattr(stu,'name','')
print(getattr(stu,'name')) # delattr(stu,'name')
print(hasattr(stu,'name')) #False print(hasattr(stu,'www')) #True 案例2:
class MY_CMD:
def dir(self):
os.system('dir') def ipconfig(self):
os.system('ipconfig') cmd = MY_CMD()
while True:
name = input('请输入要执行的指令:')
if hasattr(cmd,name):
method = getattr(cmd,name)
print(method) #绑定方法: <bound method MY_CMD.dir of <__main__.MY_CMD object at 0x0000021FFF8765F8>>
method()
else:
print('sorry this method is not exists....!')

  

7,动态导入模块:

'''
直接写import 称之为静态导入,建立在一个基础时,提前已经知道有这个模块 动态导入:指的是在需要的任何时候,通过指定字符类型,包名称来导入需要的模块 import importlib
mk = importlib.import_module(m_name)
mk 即导入成功的模块
''''' #动态导入模块.py import importlib m_name = input('请输入要导入的模块名称:').strip()
mk = importlib.import_module(m_name)
print(mk) #<module '计算属性' from 'D:\\Python_Project\\ClassRoom\\day26\\练习\\计算属性.py'> from day26.练习.build_house import conf
print(conf)
#build_house/conf.py decoration = [
'build_house.my_decoration.Table',
'build_house.my_decoration.Light',
'build_house.my_decoration.Bed',
'other_decoration.Sofa'
] #build_house/core.py import importlib
from day26.练习.build_house import conf def building():
print('毛坯房建造完成.....')
#读取用户提供配置信息,来加载用户所需要的一系列装饰品
for cls_info in conf.decoration:
# print(cls_info)
#切割类名和模块路径
m_name,cls_name = cls_info.rsplit('.',1)
# print(m_name,cls_name) #build_house.my_decoration Table #导入模块
mk = importlib.import_module(m_name)
print(mk)
#从模块中获取类
if not hasattr(mk,cls_name):
continue
cls = getattr(mk,cls_name)
obj = cls()
print(obj) building() #build_house/my_decoration.py class Table:
pass class Light:
pass class Bed:
pass

封装,封装的原理,Property ,setter ,deleter,多态,内置函数 ,__str__ , __del__,反射,动态导入模块的更多相关文章

  1. day26 封装、多态、内置函数、反射、动态导入

    今日内容 1.封装 什么是封装? 封装从字面意思上看就只将某种东西封起来装好,当我们代码中的某些方法与属性不想让外界进行访问时,就对这些属性进行特殊的处理,使这种属性或者方法不能被外界直接进行访问或者 ...

  2. python之类的多态(鸭子类型 )、封装和内置函数property

    一.多态 1.什么是多态:一个类表现出的多种状态--->通过继承来实现的例如:class Animal:passclass Dog(Animal):passclass Cat(Animal):p ...

  3. python面向对象的多态-类相关内置函数-类内置魔法函数-迭代器协议-上下文管理-04

    多态 一种事物具备不同的形态 例如:水 --> 固态.液态.气态 多态:# 多个不同对象可以相应同一个对象,产生不同的结果 首先强调,多态不是一种特殊的语法,而是一种状态,特性(多个不同对象可以 ...

  4. day15生成器send方法,递归,匿名函数,max结合匿名工作原理,常用的内置函数

    复习 ''' 1.带参装饰器 - 自定义 | wraps def wrap(info) def outer1(func): from functools import wraps @wraps(fun ...

  5. day30 继承、派生与多态,类中方法和内置函数

    目录 一.多继承出现的问题(mixins机制) 二.派生与方法重用 三.多态 1 什么是多态 2 为什么要有多态 3 python中多态的鸭子类型 四.绑定方法与非绑定方法 1 绑定方法 1.1对象的 ...

  6. Python类总结-封装(Property, setter, deleter)

    Property #property #内置装饰器函数,只在面向对象中使用 from math import pi class Circle: def __init__(self,r ): self. ...

  7. 面向对象_内置函数 property

    property 将方法伪装成为属性,可以不用加上()就可以调出其属性. 但是用__dict__,不能调出此属性 from math import pi class Circle: def __ini ...

  8. Python内置函数之-property

    property 是一个内置的装饰器函数,只在面向对象中使用 求一个圆的周长和面积 # 周长和面积都是通过类的方法得到from math import pi class Cricle: def __i ...

  9. Python内置函数property()使用实例

    class Shuxing(): def __init__(self, size = 10): self.size = size def getSize(self): print('getSize') ...

随机推荐

  1. php:判断 是否开启 SSL,CURL,ZIP,GD2,MYSQL,是否安装MEMCACHED

    对于php的开发环境,通常需要去先判断下一些扩展和服务时不时已经可用~ 看过的欢迎拍砖,给意见~~ <?php /** * 判断 是否开启 SSL,CURL,ZIP,GD2,MYSQL,是否安装 ...

  2. ubuntu上安装ansible

    1 在最新的ubuntu系统上安装ansible : sudo ape-get install ansible 2 切换到root用户 生成ssh免密登陆 ssh-keygen -t rsa ssh- ...

  3. bzoj 2301: [HAOI2011]Problem b mobius反演 RE

    http://www.lydsy.com/JudgeOnline/problem.php?id=2301 设f(i)为在区间[1, n]和区间[1, m]中,gcd(x, y) = i的个数. 设F( ...

  4. 洛谷 P1969 积木大赛

    题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成 ...

  5. Junit-@Annotation-动态代理-类加载器

    一.测试单元     概述:用于测试JAVA代码的工具类,已内置在Eclipse中;     格式:         1.在方法的上面添加@Test;         2.对被测试的方法的要求:权限- ...

  6. UVA 10037 Bridge (基础DP)

    题意: 过河模型:有n个人要渡河,每个人渡河所耗时可能不同,只有1只船且只能2人/船,船速取决于速度慢的人.问最少耗时多少才能都渡完河? 思路: n<2的情况比较简单. 考虑n>2的情况, ...

  7. 为什么我的C4C Service Request没办法Release到ERP?

    问题 UI上发现找不到Release to ERP的按钮: 但是在UI Designer里是能看到这个按钮的.检查其Visible的属性,绑到了一个Calculated Rule上面: 发现其显示在r ...

  8. 如何将SAP Multi Target应用部署到SAP云平台的Cloud Foundry环境去

    SHINA是SAP HANA Interactive Education的缩写,是一个demo应用,用于演示如何开发SAP HANA原生应用. 这个应用包含了sample数据以及HANA数据库表,vi ...

  9. 巧用代理设计模式(Proxy Design Pattern)改善前端图片加载体验

    这篇文章介绍一种使用代理设计模式(Proxy Design Pattern)的方法来改善您的前端应用里图片加载的体验. 假设我们的应用里需要显示一张尺寸很大的图片,位于远端服务器.我们用一些前端框架的 ...

  10. 2018.4.16 Java多线程实现龟兔赛跑

    龟兔赛跑(通过多线程来实现 里面的具体方法) TT.java package com.lanqiao.demo3; /** * 乌龟 * @author Administrator * */ publ ...