Python 面向对象(下)
本篇博客承接自Python 面向对象(上)
四. 继承,实现,依赖,关联,聚合,组合
五. 特殊成员
六. issubclass,type,isinstence各自的用法和区别
1. issubclass
语法: issubclass(class1, class2)
参数: class1 和 class2 都是 类
返回值: 返回 True 或 False -- 当class1是class2的家族成员时, 返回True, 否则返回False.
举例说明:
class Animal(object): pass
class Cat(Animal): pass
class BoSiCat(Cat): pass a = Animal()
c = Cat()
bsc = BoSiCat() # print(issubclass(c, Animal))
# 报错: issubclass() arg 1 must be a class
# print(issubclass(Cat, a))
# 报错: issubclass() arg 2 must be a class or tuple of classes print(issubclass(BoSiCat, Cat))
# 输出结果: True
print(issubclass(BoSiCat, Animal))
# 输出结果: True
需要强调的是, issubclass()中的两个参数都是类!
2. type
语法: type(obj)
参数: obj表示一个对象
返回值: 返回创建这个对象的类(也即是对象obj的数据类型)
举例说明:
class Animal(object): pass
class Cat(Animal): pass
class BoSiCat(Cat): pass a = Animal()
c = Cat()
bsc = BoSiCat() print(type(a)) # 精准地判断出创建对象a的类是什么, 给出对象a的数据类型
# <class '__main__.Animal'>
print(type(c))
# <class '__main__.Cat'>
3. isinstence
语法: isinstance(obj, classinfo)
参数:
obj -- 实例对象
classinfo -- 可以是直接或间接类名、基本类型或者由它们组成的元组
返回值: 返回True或False -- 如果对象obj的类型与参数二classinfo的类型相同则返回 True,否则返回 False
举例说明:
class Animal(object): pass
class Cat(Animal): pass
class BoSiCat(Cat): pass a = Animal() # 实例化
c = Cat()
bsc = BoSiCat() # print(isinstance(c, a))
# 报错: isinstance() arg 2 must be a type or tuple of types print(isinstance(c, Animal)) # 判断对象c是否是类Animal
# 输出结果: True
print(isinstance(Cat, Animal)) # 判断类Cat是否是类Animal
# 输出结果: False
print(isinstance(Cat, type)) # 判断类Cat是否是类type
# 输出结果: True
根据上面的例子可以总结出:
(1) isinstance()中的第一个参数必须是实例对象, 第二个参数必须是类名或由类名组成的元组.
(2) 在上面的示例中, 注意到 print(isinstance(Cat, type)) 的执行结果是 True. 事实上, 如果把类也当作一个对象来看, 那么"类"这个对象是"type"类型的, 即"类"是"type"的家族成员.
七. 面向对象中方法与函数的辨别
在类外部: 都是函数
在类内部:
(1)属性 -- 无论谁访问, 属性既不是函数也不是方法
(2)实例方法: 对象访问是方法, 类名访问是函数
(3)静态方法: 无论谁访问, 静态方法都是函数
(4)类方法: 无论谁访问, 类方法都是方法
1. 在类的外部
def func():
print("我是函数func") print(func)
# 执行结果: <function func at 0x00000188BC263E18>
得出结论:
在类外面定义的函数一定是函数
2. 在类的内部
class Foo:
def instance_method(self):
print("这里是实例方法")
return "这里是实例方法的返回值"
@staticmethod
def static_method():
pass
@classmethod
def class_method(cls):
pass
@property
def age(self):
return 10
举例说明
(1)属性
class Foo:
@property
def age(self):
return 10 # 引入两个模块
from types import FunctionType, MethodType # 定义一个函数,判断该参数是函数还是方法
def function_method_judge(arg):
print(isinstance(arg, FunctionType))
print(isinstance(arg, MethodType)) # 调用函数
function_method_judge(Foo().age)
print(Foo().age)
# 执行结果:
# False
# False
#
得出结论:
在@property的声明下, 我们定义的代码有着方法的表现形式(例如,他是有返回值的),但它既不是函数也不是方法.
(2)实例方法
a.对象去访问:
# 定义一个实例方法
class Foo:
def instance_method(self):
print("这里是实例方法")
return "这里是实例方法的返回值" # 实例化
f = Foo() # 对象访问实例方法名
print(f.instance_method)
以上代码的执行结果是:
<bound method Foo.instance_method of <__main__.Foo object at 0x0000017D7D11AA90>>
得出结论:
对象访问实例方法 --> "实例方法"是"方法"
b.类名去访问:
# 定义一个实例方法
class Foo:
def instance_method(self):
print("这里是实例方法")
return "这里是实例方法的返回值" # 类名访问实例方法
print(Foo.instance_method)
以上代码的执行结果是:
<function Foo.instance_method at 0x000002738C22B9D8>
得出结论:
类名访问实例方法 --> "实例方法"是"函数"
(3)静态方法
# 定义一个静态方法
class Foo:
@staticmethod
def static_method():
pass # 实例化
f = Foo() # 对象访问静态方法
print(f.static_method)
# 类名访问静态方法
print(Foo.static_method)
以上代码的执行结果分别是:
<function Foo.static_method at 0x0000018E170BB9D8>
<function Foo.static_method at 0x0000018E170BB9D8>
得出结论:
无论是谁去访问静态方法, 静态方法都是函数
(4)类方法
class Foo:
@classmethod
def class_method(cls):
pass # 实例化
f = Foo() # 对象访问类方法
print(f.class_method)
# 类名访问类方法
print(Foo.class_method)
以上代码的执行结果分别是:
<bound method Foo.class_method of <class '__main__.Foo'>>
<bound method Foo.class_method of <class '__main__.Foo'>>
得出结论:
无论是谁去访问类方法, 类方法都是方法
八. 反射
反射: 利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动.
1. hasattr
描述: hasattr()函数用于判断对象是否包含对应的属性.
语法: hasattr(object, name)
参数:
object -- 对象
name -- 字符串类型的属性名字(强调: name是属性名)
返回值: 如果对象有名字叫name的属性, 返回True, 否则返回False.
举例说明:
# 创建类
class Person(object):
def __init__(self, name, age, hobby):
self.name = name
self.age = age
self.hobby = hobby # 实例化
p = Person("王菲", 45, "唱歌") # 判断对象p是否有"name", "age", "hobby"属性
print(hasattr(p, "name"))
print(hasattr(p, "age"))
print(hasattr(p, "hobby"))
以上代码执行结果分别是:
True
True
True
得出结论: hasattr()函数用于判断对象是否包含"字符串类型的属性名"所对应的属性, 如果包含返回True, 否则返回False.
2. getattr
描述: getattr() 函数用于返回一个对象属性的值.
语法: getattr(object, name)
参数:
object -- 对象
name -- 字符串类型的属性名字
返回值: 如果对象包含"该属性名对应的属性", 返回属性的值, 否则抛出一个异常: AttributeError.
举例说明:
# 创建类
class Person(object):
def __init__(self, name, age, hobby):
self.name = name
self.age = age
self.hobby = hobby # 实例化
p = Person("王菲", 45, "唱歌") # 从对象p中拿到对应的值
value1 = getattr(p, "name")
value2 = getattr(p, "age")
value3 = getattr(p, "hobby")
print(value1, value2, value3) # 尝试去拿一个p中没有的属性gender
value4 = getattr(p, "gender")
以上代码执行结果是:
王菲 45 唱歌
AttributeError: 'Person' object has no attribute 'gender'
3. setattr
描述: setattr()函数常常与getattr()配合使用, 用于设置属性值, 该属性必须存在.
语法: setattr(object, name, value)
参数:
object -- 对象
name -- 字符串类型的属性名字
value -- 属性值
返回值: 无
举例说明:
# 创建类
class Person(object):
def __init__(self, name, age, hobby):
self.name = name
self.age = age
self.hobby = hobby # 实例化
p = Person("王菲", 45, "唱歌") # 从对象p中拿到对应的值
value1 = getattr(p, "name")
value2 = getattr(p, "age")
value3 = getattr(p, "hobby")
print(value1, value2, value3) # 重新设置对象p的属性值
setattr(p, "name", "刘德华")
setattr(p, "age", 57)
print(p.name, p.age, p.hobby) # 尝试给对象p设置一个他没有的属性
setattr(p, "gender", "男")
print(p.gender)
以上代码执行结果:
王菲 45 唱歌
刘德华 57 唱歌
男
事实上, 在实际工作中, 当我们需要使用setattr()函数时, 我们必须征得相关领导或同事的同意才能进行操作, 否则, 当有人使用我们的代码时, 会给他们带来很大的困扰与不便. 因此, 对于setattr()函数我们要谨慎使用!
4. delattr
描述: delattr()函数用于删除对象的属性. 补充: delattr(obj, "name")相等于del obj.name
语法: delattr(object, name)
参数:
object -- 对象
name -- 字符串类型的属性名字, 对象必须包含该属性名对应的属性, 否则会抛出异常.
返回值: 无
举例说明:
# 创建类
class Person(object):
def __init__(self, name, age, hobby):
self.name = name
self.age = age
self.hobby = hobby # 实例化
p = Person("王菲", 45, "唱歌")
print(p.name, p.age, p.hobby)
# 执行结果: 王菲 45 唱歌 # 尝试删除一个对象的已有属性
delattr(p, "hobby")
# print(p.hobby)
# 抛出一个异常:AttributeError: 'Person' object has no attribute 'hobby' # 尝试删除一个对象没有的属性
# delattr(p, "gennder")
# 抛出一个异常: AttributeError: gennder
结论:
当使用delattr()函数删除对象的属性后, 我们就无法再访问该属性了. 另外, 我们不能删除对象所没有的属性.
九. 异常处理
待补充
参考资料: 错误处理
十. MD5加密
步骤说明:
# 1. 引入模块hashlib
import hashlib # 2. 创建一个MD5对象
obj = hashlib.md5(b"complexity") # 这里的complexity是可以更改的, 它的作用是让我们的密文更加难以被碰撞到 # 3. 把要加密的内容转换成字节(byte)的形式交给MD5对象
obj.update("encrypted_content".encode("utf-8")) # 4. 获取密文
val = obj.hexdigest()
print(val)
# 打印结果是: acff9466e8cd1867e0a9d90755b55638 , 它就是"encrypted_content"的MD5密文
实例应用:
# 定义一个函数, 用于MD5加密
def my_md5(val):
obj = hashlib.md5(b"complexity") # 创建一个MD5对象
obj.update(val.encode("utf-8")) # 把要加密的内容转换成字节的形式交给该MD5对象
val = obj.hexdigest() # 使用hexdigest()函数获取密文, 并将之赋给变量val
return val # 返回密文
十一. 日志处理
十二. super()的用法
1. 回顾 -- 继承是什么?
待补充
2. MRO(method resolution order)
(1)经典类MRO
待补充
(2)新式类MRO
待补充
3. super()的具体用法
待补充
Python 面向对象(下)的更多相关文章
- python面向对象(下)
继承 继承描述了基类的属性如何"遗传"给派生类.一个子类可以继承它的基类的任何属性,不管是数据属性还是方法.创建子类的语法看起来与普通(新式)类没有区别,一个类名,后跟一个或多个需 ...
- Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)
Python开发[第七篇]:面向对象 详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇) 上一篇<Python 面向对象(初级篇)> ...
- Python面向对象编程(下)
本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...
- Python面向对象之反射,双下方法
一. 反射 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力(自省).这一概念的提出很快引发了计算机科学领域关于应用反射性的研究.它首先被程序 ...
- Python面向对象06 /元类type、反射、函数与类的区别、特殊的双下方法
Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3 ...
- python 面向对象专题(六):元类type、反射、函数与类的区别、特殊的双下方法
目录 Python面向对象06 /元类type.反射.函数与类的区别.特殊的双下方法 1. 元类type 2. 反射 3. 函数与类的区别 4. 特殊的双下方法 1. 元类type type:获取对象 ...
- python 面向对象初级篇
Python 面向对象(初级篇) 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发" ...
- Python 面向对象 基础
编程范式概述:面向过程 和 面向对象 以及函数式编程 面向过程:(Procedure Oriented)是一种以事件为中心的编程思想. 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现 ...
- python面向对象进阶(八)
上一篇<Python 面向对象初级(七)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使 ...
随机推荐
- 串口+RS485驱动
其实RS485不算什么协议,只是物理层做了差分传输,AB两线的电压差来表示0,1,0,1,可靠性和距离更加好,因此,一个串口外设只能作为半双工使用,而RS232是可以全双工的. max485模块可以直 ...
- P3254——DP&&入门
题目 给定一个$n \times m$的$01$矩形,选择其中为$1$的位置,要求互不相邻,问方案数. 解决方案 直接dp因为状态较多,数组很难直接表示出来,我们采用二进制状态压缩存储. 用$dp[i ...
- HTTP 协议讲解
http请求由三部分组成,分别是:请求行.消息报头.请求正文 HTTP(超文本传输协议)是一个基于请求与响应模式的.无状态的.应用层的协议,常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接 ...
- 中介者模式(Mediator)---行为型
1 基础知识 定义:用一个中介对象来封装一系列的对象交互.中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互. 本质:封装交互 使用场景:(1)如果一组对象之间的 ...
- Python基础--01小项目体现的基础知识
part1:猜拳游戏 #coding=utf-8 #当有汉语时可能编译器不认识,需要定义代码 ''' 多行注释 写这个程序是为了熟悉python的基本语法 这是第一个小例子包含简单的if判断,循环和输 ...
- EnumHelper.cs
网上找的,还比较实用的: using System; using System.Collections.Generic; using System.ComponentModel; using Syst ...
- UVALive 7308 Tom and Jerry 猫抓老鼠 物理题
题目链接: 就是一个老鼠在环上一速度v开始绕环走,一只猫从圆心出发,任意时刻圆心,猫,老鼠三者在一条直线上,且速度也是v,求多久后猫抓到老鼠. #include <cstdio> #inc ...
- javascript数据结构之顺序表
关于线性表的概念这里就不赘述了,可以自行百度和查阅资料,线性表按照存储(物理)结构分为顺序存储和链式存储,每种存储方式的不同决定了它的实现代码是不同的: 顺序存储的特点就是在内存中选一块连续的地址空间 ...
- Linux+CLion+树莓派远程编译时,Cmake编译出现undefined reference to `vtable for MainWindow'的解决办法
在win+CLion上进行远程qt开发时碰到以下错误: 错误提示: undefined reference to `vtable for MainWindow' 原因:源文件的目录结构有问题?? 解决 ...
- PAT L2-001 紧急救援 —— (多参数最短路)
和天梯中的直捣黄龙差不多.但是,通过这个问题,我对多参数最短路又有了更深一层的了解. 这题因为点数比较多,所以如果直接用大力学长的在G上dfs找最短路径的条数的话,会TLE,所以需要剪枝.剪枝方法是, ...