今日内容

1、封装

什么是封装?

封装从字面意思上看就只将某种东西封起来装好,当我们代码中的某些方法与属性不想让外界进行访问时,就对这些属性进行特殊的处理,使这种属性或者方法不能被外界直接进行访问或者修改,这种方法就称之为封装

但是,在python中没有完全意义的封装,封装只是在内部进行了变形,使其使用原变量名不能进行访问

同时,有些父类的方法,如果不想让子类进行覆盖就将父类的方法设置为私有属性

封装的方法:

在python中如果需要对某个属性或方法进行封装是只需要在变量名前设置为__开头的即可,此时在在外界进行访问时就不能访问这个属性或方法

封装的原理:

我们在进行封装时,实际上是对封装的属性或方法进行了变形,当类进行定义时,如果属性或者方法是以__开头的就会对这个属性进行变形,变形方式为:

__前面加上_类名变为_类名__属性名或方法名

注意:变形的操作只在定义类时执行一次

在python中,并不会限制用户访问私有属性及方法,私有的属性及方法还是可以被外界访问的,只要自己将方法前面添加_类名就可以访问私有的属性及方法

其实很多时候你去调用一个模块的功能时会遇到单下划线开头的(socket.socket,sys.home,sys._clear_type_cache),这些都是私有的,原则上是供内部调用的

class Person:
def __init__(self,name,age):
self.name = name
self.__age = age p = Person("lee",20)
print(p.name)
# print(p.__age) # AttributeError: 'Person' object has no attribute '__age'
p.__age = 18
print(p.__age) #
print(p.__dict__) # {'name': 'lee', '_Person__age': 20, '__age': 18}

从上例中可以看出:当把属性设置为__开头时就不能在外界直接访问及修改了,如果直接使用 对象.__方法名进行设置,不是对原来的方法进行设置,而是在名称空间直接设置了一个新的变量名

封装的目的

封装不是单纯意义的隐藏,封装会明确的区分内外,在类的内部可以直接使用但是在外部就不可以直接使用

封装的目的:

1、提高安全性:提高安全性主要是针对属性而言的,封装后属性的值不能直接被外界访问及修改,可以保证数据的安全性

2、隔离复杂度:隔离复杂度是针对于方法而言的,我们将类中具体的逻辑私有化,再将其封装到一个方法中供外界访问,这样用户只需要进行一次调用就可以直接访问,对用户而言降低了复杂度

class ATM:
def __card(self):
print('插卡') def __auth(self):
print('用户认证') def __input(self):
print('输入取款金额') def __print_bill(self):
print('打印账单') def __take_money(self):
print('取款') def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__take_money()
self.__print_bill() atm = ATM()
atm.withdraw()
# 插卡
# 用户认证
# 输入取款金额
# 取款
# 打印账单

上述方法对于用户而言只是进行了取款操作,但是在类的内部通过私有方法已经进行了一系列操作

property装饰器

property是一个属性装饰器,可以将方法伪装成属性

实际上,property是一个类,在使用是就是调用这个类产生一个实例化对象,这个对象经常使用的方法有三种:`

getter setter deleter`

其中:

getter在调用property时就会自动调用

setter在设置方法时调用

deleter在删除方法时调用

property使用场景一:供私有属性使用
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age def get_age(self):
print(self.__age) def set_age(self,new_age):
self.__age = new_age
p =Person("lee",18)
p.name
p.get_age()

通过上例中的方法可以进行私有属性的访问及修改,但是这样我们在访问name属性时可以使用 对象.name进行访问,但是访问age属性是就需要使用 对象.get_age() 来进行访问,同样都是属性但是访问方法却不相同,为了使用户对属性的访问方式相同,此时就需要使用 propety 装饰器

class Person:
def __init__(self, name, age):
self.name = name
self.__age = age @property
def age(self):
return (self.__age) @age.setter
def age(self, new_age):
self.__age = new_age @age.deleter
def age(self):
del self.__dict__["_Person__age"] p = Person("lee", 18)
print(p.name)
print(p.age)
p.age = 20
del p.age
print(p.age) # 会报错

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("egon",1.7,80)
# p.weight = 60
# print(p.BMI)

2、多态

什么是多态?

多态就是一种事物的多种形态

oop中多态就是不同类型的对象可以响应同一种方法,得到不同的响应结果

# 定义一个动物的类
class Animal:
def bark(self):
pass def sleep(self):
pass def run(self):
pass # 定义一个猫类
class Cat(Animal):
def bark(self):
print("喵喵喵") def sleep(self):
print("躺着睡") def run(self):
print("四条腿跑") # 定义一个人类
class Person(Animal):
def bark(self):
print("hi") def run(self):
print("四条腿跑") def sleep(self):
print("躺着睡") # 定义一个狗类
class Dog(Animal):
def bark(self):
print("汪汪汪") def sleep(self):
print("侧躺着睡") def run(self):
print('四条腿跑') # 定义一个管理员类用来管理动物
class ManagementAnimal:
def Manage(self,animal):
animal.bark()
animal.sleep()
animal.run() dog = Dog()
p = Person()
cat = Cat() m = ManagementAnimal()
m.Manage(p)
m.Manage(dog)
m.Manage(cat)

在上例中:

动物类、狗类、猫类、人类等产生的不同对象可以同时调用barksleeprun等方法,但是这些方法的执行结果是不相同的,这种就称之为多态

从上述例子可以看出多态的优点:

1、可以是对象的调用更加的灵活,不论对象如何改变,调用对象方法的方式是相同的

2、可以提高程序的扩展性,在创建一个新的动物类是不需要更改Manager的代码就能进行使用

在python中如果想要强制性的规定动物类必须具有这些个属性,可以导入abc模块

import abc

class Animal(metaclass=abc.ABCmeta)
@abc.abstractmethod
def bark(self):
pass def sleep(self):
pass
class Cat(Animal):
def sleep(self):
print("正在叫!") cat = Cat()

如果调用了abc模块,那么子类继承后在进行实例化时,如果不将类中含有abstractmethod的方法全部重新定义,就会报错,其中没有abstractmethod的方法不受限制

虽然在Python中可以使用abc模块进行限制,但是python编程更多的是建议,而不是约束

所以python中更多的是建议用户使用鸭子类型

3、内置函数

__str__

_str_是系统内置的函数,当我们需要对类转化成字符串时就会执行

类中的__str__
该方法在object中有定义 默认行为 返回对象类型以及地址 <__main__.Person object at 0x0000016F450C7390>
在将对象转为字符串时执行
注意:返回值必须为字符串类型
子类可以覆盖该方法来完成 对打印内容的自定义

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)
# print(p) #在打印前都会现将要打印的内容转为字符串 通过调用__str__函数 str(p)

__del__

_del_是系统内置的函数,当我们需要删除对象时就会在删除的前一步自动执行

当对象被删除前会自动调用 该方法
声明时候会删除对象?
1.程序运行结束 解释器退出 将自动删除所有数据
2.手动调用del 时也会删除对象

注意:该函数不是用来删除对象的

使用场景
当你的对象在创建时,开启了不属于解释器的资源 例如打开了一个文件
必须保证当对象被删除时 同时关闭额外的资源 如文件

也称之为析构函数 构造 的反义词
构造 指的是从无到有
析构 值从有到无
简单的说就对象所有数据全部删除

总结:__del__该函数 用于 在对象删除前做一些清理操作

# 假设要求每一个person对象都要绑定一个文件
class Person:
def __init__(self,name,path,mode="rt",encoding="utf-8"):
self.name = name
self.file = open(path,mode,encoding=encoding) # 读取数据的方法
def read_data(self):
return self.file.read() def __del__(self):
print("del run!")
self.file.close() # p = Person("jack") # a = 10 # f = open("test.txt")
# print(f.read())
# f.close() p2 = Person("rose","本周内容")
print(p2.read_data())

4、反射

英文中叫反省 (自省)

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

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

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

涉及到的方法:
hasattr 判断是否存在某个属性
getattr 获取某个属性的值
setattr 新增或修改某个属性
delattr 删除某个属性 案例:
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)
method()
else:
print("sorry this method is not exists....!")

5、动态导入模块

直接写import 称之为静态导入 建立在一个基础上:提前已经知道有这个模块

动态导入 指的是 在需要的任何时候 通过指定字符串类型的包名称来导入需要的模块

import importlib mk = importlib.import_module(m_name) mk 即导入成功的模块

该方式常用在框架中 因为框架设计者不可能提前预知后续需要的模块和类

day26 封装、多态、内置函数、反射、动态导入的更多相关文章

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

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

  2. day28 面向对象:反射,内置函数,类的内置方法

    面向对象进阶博客地址链接: http://www.cnblogs.com/Eva-J/articles/7351812.html 复习昨日内容: # 包 # 开发规范 # # hashlib # 登录 ...

  3. python语法基础-函数-内置函数和匿名函数-长期维护

    ##################     内置函数        #######################  """ 一共是 68个内置函数: 反射相关的内置函 ...

  4. 封装,封装的原理,Property ,setter ,deleter,多态,内置函数 ,__str__ , __del__,反射,动态导入模块

    1,封装 ## 什么是封装 what 对外隐藏内部的属性,以及实现细节,并给外部提供使用的接口 学习封装的目的:就是为了能够限制外界对内部数据的方法 注意 :封装有隐藏的意思,但不是单纯的隐藏 pyt ...

  5. 绑定与非绑定方法及反射,isinstance和issubclass内置函数

    目录 绑定方法与非绑定方法 1.绑定方法 2.非绑定方法(staticmethod) isinstance和issubclass 内置函数 1.isinstance 2.issubclass 反射(面 ...

  6. Python-老男孩-01_基础_文件IO_函数_yield_三元_常用内置函数_反射_random_md5_序列化_正则表达式_time

    Python2.7 缩进统一: 约定  常量 大写 , 变量  小写 判断一个变量在内存中的地址,也能看出是不是一个值 id()函数 >>> x = 'abc' >>&g ...

  7. python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法

    一.内置函数补充 1.isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() print(isinstan ...

  8. 面向对象 反射 和item系列和内置函数和__getattr__和__setattr__

    反射 反射主要用在网络编程中, python面向对象的反射:通过字符串的形式操作对象相关的属性.python的一切事物都是对象. 反射就是通过字符串的形式,导入模块:通过字符串的形式,去模块寻找指定函 ...

  9. Python 面向对象 (补充) , 反射 , 内置函数

    面向对象中内置函数 issubclass方法: 检查第一个参数是否是第二个参数的子子孙孙类     返回  :   是一个布尔值 class Base(object): pass class Foo( ...

随机推荐

  1. hdu 2510

    Tiling_easy version Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...

  2. 小程序弹框wx.showModal、wx.showActionSheet、wx.showToast

    wx.showModal wx.showModal({ title: '删除图片', content: '确定要删除该图片?', showCancel: true,//是否显示取消按钮 cancelT ...

  3. 在windows使用gvim的感受

    用新下载的gvim写几行代码习惯一下,感觉vim用起来要比atom占用的内存少多了,更加的便捷.由于之前一直在用sublime text2,虽然我也很喜欢ST,但我还是抱着膜拜的心态来试了试gvim, ...

  4. Linux 删除文件夹和文件的命令(强制删除包括非空文件)

    linux删除目录很简单,很多人还是习惯用rmdir,不过一旦目录非空,就陷入深深的苦恼之中,现在使用rm -rf命令即可.直接rm就可以了,不过要加两个参数-rf 即:rm -rf 目录名字-r 就 ...

  5. 数据结构-用C++实现一个二叉树,递归方法中序遍历

    1:二叉排序树,又称二叉树.其定义为:二叉排序树或者空树,或者是满足如下性质的二叉树. (1)若它的左子树非空,则左子树上所有节点的值均小于根节点的值. (2)若它的右子树非空,则右子树上所有节点的值 ...

  6. Leetcode题目206.反转链表(简单)

    题目描述: 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: ...

  7. koa 项目实战(六)注册接口加密

    1.创建工具类 根目录/config/tools.js const bcrypt = require('bcryptjs'); const tools = { enbcrypt(password) { ...

  8. IDEA Method definition shorthands are not supported by current JavaScript version

    sentinel-dashboard前端用到了AngularJS v1.4.8,在IDEA里修改js,触发js验证时有一些js文件会出现红色波浪线. 在代码行里鼠标一上去提示信息:Method def ...

  9. MySQL:行锁、表锁、乐观锁、悲观锁、读锁、写锁

    1.锁的分类 1.1从对数据操作的类型来分 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响. 结论1: --如果某一个会话 对A表加了read锁,则 该会话 可以对A表进行读操作 ...

  10. OpenCL Workshop 1 —— 数字音频滤波

    Introduction 这两年深度学习大火,Cuda跟着吃红利,OpenCL发展也很快.虽然OpenCL不是事实上的标准,但是作为开放标准,适应性是很强的,除了显卡之外,CPU/FPGA上都可以执行 ...