面向对象进阶

一、关于面向对象的两个内置函数

isinstance   判断类与对象的关系    isinstance(obj,cls)检查obj是否是类 cls 的对象,返回值是bool值

issubclass     判断类与类的关系             issubclass(sub, super)检查sub类是否是 super 类的派生类,返回值是bool值

class A:
pass
class B(A):
pass
a = A()
print(isinstance(a,A))
print(issubclass(B,A))
print(issubclass(A,B)) >>>
True
True
False

关于类的内置函数

二、反射

什么是反射?

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的

提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

ps:

  eval  的功能和反射有点类似,但是 eval 在操作字符串时有很大的安全隐患,反射没有安全隐患。

四个可以实现自省的函数

下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

1、getattr(object, name[,default])
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号。

class A:
def func(self):
print('in func') a = A()
a.name = 'alex'
a.age = 63 ret = getattr(a,'name') # 通过变量名的字符串形式取到的值
print(ret)
print(a.__dict__) 变量名 = input('>>>') # func
print(getattr(a,变量名))
print(a.__dict__[变量名]) 》》》
alex
{'name': 'alex', 'age': 63}
>>>age
63
63

反射对象的属性

class A:
def func(self):
print('in func') a = A() a.func()
ret = getattr(a,'func')
print(ret) #不加括号只能打印一个内存地址
ret() 》》》
in func
<bound method A.func of <__main__.A object at 0x00000250C461E668>>
in func

反射对象的方法

class A:
price = 20
@classmethod
def func(cls):
print('in func') print(getattr(A,'price')) 》》》
20

反射类的属性

#需要使用到装饰器    classmethod     staticmethod

class A:
price = 20
@classmethod
def func(cls):
print('in func') if hasattr(A,'func'):
getattr(A,'func')() 》》》
in func

反射类的方法

#新建一个my.py
#内容
day = 'Monday' # 周一 def wahaha():
print('wahahaha') class C:
pass #在另一个py文件里运行
import my
print(my.day)
print(getattr(my,'day')) 》》》
Monday
Monday

反射模块的属性

#新建一个my.py
#内容
day = 'Monday' # 周一 def wahaha():
print('wahahaha') class C:
pass #在另一个py文件里运行 getattr(my,'wahaha')() 》》》
wahahaha

反射模块的方法

#新建一个my.py
#内容
day = 'Monday' # 周一 def wahaha():
print('wahahaha') class C:
pass #在另一个py文件中运行 import my
print(getattr(my,'C')()) 》》》
<my.C object at 0x0000029F28E9E080>

反射模块里的类

# time
# asctime
import time
print(getattr(time,'time')())
print(getattr(time,'asctime')()) 》》》
1516608195.0811734
Mon Jan 22 16:03:15 2018

内置模块也能反射

def qqxing():
print('qqxing')
year = 2018
import sys
print(sys.modules['__main__'].year)
print(getattr(sys.modules['__main__'],'year')) 》》》
2018
2018

反射自己模块中的变量

def qqxing():
print('qqxing')
year = 2018
import sys getattr(sys.modules['__main__'],'qqxing')()
变量名 = input('>>>')
print(getattr(sys.modules[__name__],变量名)) 》》》
qqxing
>>>year
2018

反射自己模块中的函数

import time
print(time.strftime('%Y-%m-%d %H:%M:S'))
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S')) 》》》
2018-01-22 16:08:S
2018-01-22 16:08:S

要反射的函数可以有参数

2、hasattr(object, name)
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
需要注意的是name要用括号括起来

class A:
name = 'xiaoming'
def run(self):
return 'gogogo'
a = A()
print(a.run())
print(hasattr(a,'name')) #判断对象是否有 name 属性
print(hasattr(a,'run')) #判断对象是否有 run 方法
print(hasattr(A,'run')) #判断类是否有 run 属性
print(hasattr(A,'rn')) 》》》
gogogo
True
True
True
False

3、setattr(object, name, values)
给对象的属性赋值,若属性不存在,先创建再赋值。

class A:
pass
a = A()
setattr(a,'name','nezha')
setattr(A,'name','alex')
print(A.name)
print(a.name)

4、delattr(object, name)

删除一个变量,删除指定对象的指定名称的属性,和setattr函数作用相反,当属性不存在的时候,会报错,不能删除对象的方法。

class A:
pass
a = A()
setattr(a,'name','nezha')
setattr(A,'name','alex') delattr(a,'name')
print(a.name)
delattr(A,'name')
print(a.name) 》》》
alex
Traceback (most recent call last):
File "D:/Python学习/Python/学习资料/学习视频/day27/2.反射.py", line 122, in <module>
print(a.name)
AttributeError: 'A' object has no attribute 'name'

在删除时,注意作用域。对象的属性里没有可以去找类的属性,但不能去object这个父类找

三、双下方法

内置的类方法 和 内置的函数之间有着千丝万缕的联系

__str__和__repr__

改变对象的字符串显示__str__,__repr__

自定制格式化字符串__format__

#_*_coding:utf-8_*_

format_dict={
'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
}
class School:
def __init__(self,name,addr,type):
self.name=name
self.addr=addr
self.type=type def __repr__(self):
return 'School(%s,%s)' %(self.name,self.addr)
def __str__(self):
return '(%s,%s)' %(self.name,self.addr) def __format__(self, format_spec):
# if format_spec
if not format_spec or format_spec not in format_dict:
format_spec='nat'
fmt=format_dict[format_spec]
return fmt.format(obj=self) s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1) '''
str函数或者print函数--->obj.__str__()
repr或者交互式解释器--->obj.__repr__()
如果__str__没有被定义,那么就会使用__repr__来代替输出
注意:这俩方法的返回值必须是字符串,否则抛出异常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
class B:

     def __str__(self):
return 'str : class B' def __repr__(self):
return 'repr : class B' b=B()
print('%s'%b)
print('%r'%b) %s和%r
# obj.__str__  str(obj)
# obj.__repr__ repr(obj) class Teacher:
def __init__(self,name,salary):
self.name = name
self.salary = salary
def __str__(self):
return "Teacher's object :%s"%self.name
def __repr__(self):
return str(self.__dict__)
def func(self):
return 'wahaha'
nezha = Teacher('哪吒',250)
print(nezha) # 打印一个对象的时候,就是调用a.__str__
print(repr(nezha))
print('>>> %r'%nezha) #a.__str__ --> object
# object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址
# l = [1,2,3,4,5] # 实例化 实例化了一个列表类的对象
# print(l)
# %s str() 直接打印 实际上都是走的__str__
# %r repr() 实际上都是走的__repr__
# repr 是str的备胎,但str不能做repr的备胎 # print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串
# 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。
# repr(),只会找__repr__,如果没有找父类的

 ps:

内建函数str()和repr() (representation,表达,表示)或反引号操作符(``)可以方便地以字符串的方式获取对象的内容、类型、数值属性等信息。str()函数得到的字符串可读性好(故被print调用),而repr()函数得到的字符串通常可以用来重新获得该对象,通常情况下 obj==eval(repr(obj)) 这个等式是成立的。这两个函数接受一个对象作为其参数,返回适当的字符串。

事实上repr()和``做一样的事情,返回一个对象的“官方”字符串表示。其结果绝大多数情况下(不是所有)可以通过求值运算(内建函数eval())重新得到该对象。

str()则不同,它生成一个对象的可读性好的字符串表示,结果通常无法用eval()求值,但适合print输出。

__del__

析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,

所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:

    def __del__(self):
print('执行我啦') f1=Foo()
del f1
print('------->') #输出结果
执行我啦
-------> 简单示范

__call__

Python中的__call__允许程序员创建可调用的对象(实例),默认情况下, __call__()方法是没有实现的,这意味着大多数实例是不可调用的。然而,如果在类定义中覆盖了这个方法,那么这个类的实例就成为可调用的。

class A:
def __init__(self,name):
self.name = name
def __call__(self):
'''
打印这个对象中的所有属性
:return:
'''
for k in self.__dict__:
print(k,self.__dict__[k])
a = A('alex')() #后面的括号可以直接让__call__(self)函数执行 》》》
name alex

__len__

在执行len()时会自动触发内部的__len__方法

class A:
def __init__(self):
self.a = 1
self.b = 2 def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))

item系列

__getitem__         __setitem__           __delitem__

类似字典的用法

class Foo:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex def __getitem__(self, item):
if hasattr(self,item):
return self.__dict__[item] def __setitem__(self, key, value):
self.__dict__[key] = value def __delitem__(self, key):
del self.__dict__[key] f = Foo('wangming',38,'男')
print(f['name'])
f['hobby'] = '男'
print(f.hobby,f['hobby'])
del f.hobby # object 原生支持 __delattr__
del f['hobby'] # 通过自己实现的
print(f.__dict__)

__new__

构造方法 : 创建一个对象

class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A, *args, **kwargs) a = A()
print(a.x) 》》》
in new function
in init function
1
#单例模式
#一个类 始终 只有 一个 实例
#当你第一次实例化这个类的时候 就创建一个实例化的对象
#当你之后再来实例化的时候 就用之前创建的对象 class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance one = Singleton()
two = Singleton() two.a = 3
print(one.a)
#
# one和two完全相同,可以用id(), ==, is检测
print(id(one))
#
print(id(two))
#
print(one == two)
# True
print(one is two) 单例模式 单例模式

__eq__

__eq__ 定义了类的等号(==)行为

可以去重

class A:
def __init__(self):
self.a = 5
self.b = 2 def __eq__(self,obj):
if self.a == obj.a and self.b == obj.b:
return True
a = A()
b = A()
print(a.a)
print(a.b)
print(b.a)
print(b.b)
print(a == b) 》》》
5
2
5
2
True

__hash__

摘要算法:密码密文加密

摘要算法只能加密,没有解密功能

# 摘要算法
# import hashlib # 提供摘要算法的模块
# 不管算法多么不同,摘要的功能始终不变
# 对于相同的字符串使用同一个算法进行摘要,得到的值总是不变的
# 使用不同算法对相同的字符串进行摘要,得到的值应该不同
# 不管使用什么算法,hashlib的方式永远不变 # import hashlib # 提供摘要算法的模块
# sha = hashlib.md5()
# sha.update(b'这是密码区')
# print(sha.hexdigest()) # sha 算法 随着 算法复杂程度的增加 摘要的时间成本空间成本都会增加 # 摘要算法
# 密码的密文存储
# 文件的一致性验证
# 在下载的时候 检查我们下载的文件和远程服务器上的文件是否一致
# 两台机器上的两个文件 你想检查这两个文件是否相等
# 用户注册
# 用户 输入用户名
# 用户输入 密码
# 明文的密码进行摘要 拿到一个密文的密码
# 写入文件 # 用户的登录 import hashlib
usr = input('username :')
pwd = input('password : ')
with open('userinfo') as f:
for line in f:
user,passwd,role = line.split('|')
md5 = hashlib.md5()
md5.update(bytes(pwd,encoding='utf-8'))
md5_pwd = md5.hexdigest()
if usr == user and md5_pwd == passwd:
print('登录成功')
# 加盐    提高密码的安全等级
import hashlib # 提供摘要算法的模块
md5 = hashlib.md5(bytes('盐',encoding='utf-8')) #加盐区可以是任意字符
# md5 = hashlib.md5()
md5.update(b'')
print(md5.hexdigest())
# 动态加盐   提高密码的安全等级
# 用户名 密码
# 使用用户名的一部分或者 直接使用整个用户名作为盐
import hashlib # 提供摘要算法的模块
md5 = hashlib.md5(bytes('盐',encoding='utf-8')+b'')
# md5 = hashlib.md5()
md5.update(b'')
print(md5.hexdigest())
# 文件的一致性校验
# 文件的一致性校验这里不需要加盐

Python之面向对象四的更多相关文章

  1. python学习-第四天补充-面向对象

    python学习-第四天补充-面向对象 python 私有 --name mangling(名字修改.名字) 在命名时,通过使用两个下划线作为开头,可以使得这个变量或者函数编程私有的,但是这个其实的p ...

  2. Python进阶---面向对象的程序设计思想

    Python的面向对象 一.面向过程与面向对象的对比 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...

  3. Python之面向对象一

    引子 小游戏:人狗大战 角色:人和狗 角色属性:姓名,血量,战斗力和性别(种类) 技能:打/咬 用函数实现人打狗和狗咬人的情形 def Dog(name,blood,aggr,kind): dog = ...

  4. python基础——面向对象进阶

    python基础--面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 ...

  5. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  6. python学习------面向对象的程序设计

    一 面向对象的程序设计的由来 1940年以前:面向机器 最早的程序设计都是采用机器语言来编写的,直接使用二进制码来表示机器能够识别和执行的指令和数 据.简单来说,就是直接编写 和 的序列来代表程序语言 ...

  7. 【转】python 历险记(四)— python 中常用的 json 操作

    [转]python 历险记(四)— python 中常用的 json 操作 目录 引言 基础知识 什么是 JSON? JSON 的语法 JSON 对象有哪些特点? JSON 数组有哪些特点? 什么是编 ...

  8. 【转】Python之面向对象与类

    [转]Python之面向对象与类 本节内容 面向对象的概念 类的封装 类的继承 类的多态 静态方法.类方法 和 属性方法 类的特殊成员方法 继承层级关系中子类的实例对象对属性的查找顺序问题 一.面向对 ...

  9. Python OOP面向对象

    一.什么是面向对象的程序设计 1.面向过程 程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式. 优点是 ...

随机推荐

  1. 设计模式——原型模式(C++实现)

    #include <iostream> #include <string> using namespace std; class CPrototype { public: CP ...

  2. spring 文件模板下载多种实现方式

    针对于文件的下载,我们有很多种实现方式.业务场景是这样子的,要实现Excel文件的导入和导出功能,问题对于java的POI操作没有问题,所以实现文件的下载就相对简单,只需要从数据库取出相关的数据,针对 ...

  3. thinkphp5 taglib自定义标签教程

    学着写了一下,终于搞定了,顺便分享一下!taglib是tp框架自定义标签功能,如果你用过cms,肯定见过类似: {dede:arclist typeid='' row='' col='' titlel ...

  4. Redis数据过期策略

    1.Redis中key的的过期时间 通过EXPIRE key seconds命令来设置数据的过期时间.返回1表明设置成功,返回0表明key不存在或者不能成功设置过期时间.在key上设置了过期时间后ke ...

  5. #Python3.6.2(32位) pip安装 和 pygame 环境配置

    #首先确认电脑已经安装python ,可通过在命令行下 执行 python --version确认. 1. 到 https://pypi.python.org/pypi/setuptools/ 下载 ...

  6. Python类中的self到底是干啥的

    Python类中的self到底是干啥的 Python编写类的时候,每个函数参数第一个参数都是self,一开始我不管它到底是干嘛的,只知道必须要写上.后来对Python渐渐熟悉了一点,再回头看self的 ...

  7. 小细节,大用途,35 个 Java 代码性能优化总结!

    前言: 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,就像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用 ...

  8. hostPath Volume - 每天5分钟玩转 Docker 容器技术(148)

    hostPath Volume 的作用是将 Docker Host 文件系统中已经存在的目录 mount 给 Pod 的容器.大部分应用都不会使用 hostPath Volume,因为这实际上增加了 ...

  9. C#触发器知识总结及案例

    触发器 触发器是在对表进行插入.更新.删除操作时自动执行的存储过程,常用于强制业务规则,是一种高级约束,可以定义比用check约束更为复杂的约束.可以执行复杂的SQL语句(if/while/case) ...

  10. alpha冲刺总结随笔

    前言:前面乱乱糟糟整了一路,到最后终于可以稳定下来了.安安心心做个总结,然后把之后要做的事情都理清楚好了. 新学长似乎是个正经[并不]大腿. 看起来也不用都是一个人或者跟陈华学长两个人对半开了[突然摸 ...