一.super()

super()  : 主动调用其他类的成员

# 单继承
# 在单继承中 super,主要是用来调用父类的方法的。
class A:
def __init__(self):
self.n = 2 def add(self, m):
print('self is {0} @A.add'.format(self))
self.n += m class B(A):
def __init__(self):
self.n = 3 def add(self, m):
print('self is {0} @B.add'.format(self))
super().add(m)
self.n += 3
# 执行下面代码后, b.n 的值是多少呢?
b = B()
b.add(2)
print(b.n)
# 执行结果如下:
# self is <__main__.B object at 0x106c49b38> @B.add
# self is <__main__.B object at 0x106c49b38> @A.add
#
"""这个结果说明了两个问题:
super().add(m) 确实调用了父类 A 的 add 方法。
super().add(m) 调用父类方法 def add(self, m) 时, 此时父类中 self 并不是父类的实例而是子类的实例, 所以b.add(2) 之后的结果是 5 而不是 4 。
不知道这个结果是否和你想到一样呢?下面我们来看一个多继承的例子。""" # 多继承
# 这次我们再定义一个 class C,一个 class D: class C(A):
def __init__(self):
self.n = 4 def add(self, m):
print('self is {0} @C.add'.format(self))
super().add(m)
self.n += 4 class D(B, C):
def __init__(self):
self.n = 5 def add(self, m):
print('self is {0} @D.add'.format(self))
super().add(m)
self.n += 5
# 下面的代码又输出啥呢?
d = D()
d.add(2)
print(d.n)
# 这次的输出如下:
# self is <__main__.D object at 0x10ce10e48> @D.add
# self is <__main__.D object at 0x10ce10e48> @B.add
# self is <__main__.D object at 0x10ce10e48> @C.add
# self is <__main__.D object at 0x10ce10e48> @A.add
#
在大多数情况下, super 包含了两个非常重要的信息: 一个 MRO 以及 MRO 中的一个类。当以如下方式调用 super 时:
super(a_type, obj)
MRO 指的是 type(obj) 的 MRO, MRO 中的那个类就是 a_type , 同时 isinstance(obj, a_type) == True 。 当这样调用时:
super(type1, type2)
MRO 指的是 type2 的 MRO, MRO 中的那个类就是 type1 ,同时 issubclass(type2, type1) == True 。 那么, super() 实际上做了啥呢?简单来说就是:提供一个 MRO 以及一个 MRO 中的类 C , super() 将返回一个从 MRO 中 C 之后的类中查找方法的对象。
也就是说,查找方式时不是像常规方法一样从所有的 MRO 类中查找,而是从 MRO 的 tail 中查找。 举个栗子, 有个 MRO:
[A, B, C, D, E, object]
下面的调用:
super(C, A).foo()
super 只会从 C 之后查找,即: 只会在 D 或 E 或 object 中查找 foo 方法。 supper多继承图解:
二,特殊成员
相应语法对应
# __doc__ 输出类的描述(注释)信息
# __module__ 表示当前操作的对象在那个模块
# __class__ 表示当前操作的对象的类是什么
class C:
def __init__(self):
self.name = 'zwq'
from lib.aa import C
obj = C()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.C,即:输出类
# __init__ 构造方法,通过类创建对象时,自动触发执行。
# __del__ 析构方法,当对象在内存中被释放时,自动触发执行。一般无须定义,由解释器在进行垃圾回收时自动触发执行的
# __call__ 将对象变为可调用对象; 对象后面加括号,触发执行。
# __dict__ 类或对象中的所有成员
# __str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。
# __getitem__、__setitem__、__delitem__ # 用于索引操作,如字典。以上分别表示获取、设置、删除# 数据
# __getslice__、__setslice__、__delslice__ 该三个方法用于分片操作
# __iter__ 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__
# __new__ 和 __metaclass__
# __enter__ ,__exit__ with 对象 自动执行__enter__ / __exit__
class Foo(object):

    def __init__(self,a1,a2):
self.a1 = a1
self.a2 = a2 def __call__(self, *args, **kwargs):
print(11111,args,kwargs)
return 123 def __getitem__(self, item):
print(item)
return 8 def __setitem__(self, key, value):
print(key,value,111111111) def __delitem__(self, key):
print(key) def __add__(self, other):
return self.a1 + other.a2 def __enter__(self):
print('')
return 999 def __exit__(self, exc_type, exc_val, exc_tb):
print('') # 1. 类名() 自动执行 __init__
# obj = Foo(1,2) # 2. 对象() 自动执行 __call__
# ret = obj(6,4,2,k1=456) # 3. 对象['xx'] 自动执行 __getitem__
# ret = obj['yu']
# print(ret) # 4. 对象['xx'] = 11 自动执行 __setitem__
# obj['k1'] = 123 # 5. del 对象[xx] 自动执行 __delitem__
# del obj['uuu'] # 6. 对象+对象 自动执行 __add__
# obj1 = Foo(1,2)
# obj2 = Foo(88,99)
# ret = obj2 + obj1
# print(ret) # 7. with 对象 自动执行 __enter__ / __exit__
# obj = Foo(1,2)
# with obj as f:
# print(f)
# print('内部代码')

三,构造方法

class Foo(object):
def __init__(self, a1, a2): # 初始化方法
"""
为空对象进行数据初始化
:param a1:
:param a2:
"""
self.a1 = a1
self.a2 = a2 def __new__(cls, *args, **kwargs): # 构造方法
"""
创建一个空对象
:param args:
:param kwargs:
:return:
"""
return object.__new__(cls) # Python内部创建一个当前类的对象(初创时内部是空的.). obj1 = Foo(1,2)
print(obj1) obj2 = Foo(11,12)
print(obj2)

四,isinstance(obj,cls), issubclass(sub,super)和type;

isinstance(obj,cls)

检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
class Base(object):
pass class Foo(Base):
pass obj1 = Foo()
print(isinstance(obj1,Foo)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
print(isinstance(obj1,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。

issubclass(sub,super)

  检查sub类是否是 super 类的派生类

issubclass
class Base(object):
pass class Foo(Base):
pass class Bar(Foo):
pass print(issubclass(Bar,Base)) # 检查第一个参数是否是第二个参数的 子子孙孙类

type:

#type:获取当前对象是由那个类创建。
"""
class Foo(object):
pass obj = Foo() print(obj,type(obj)) # 获取当前对象是由那个类创建。
if type(obj) == Foo:
print('obj是Foo类型')
"""

五,反射

1 什么是反射

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

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

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

四个可以实现反射(自省)的函数

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

#记忆:
getattr # 根据字符串的形式,去对象中找成员,返回这个成员的值。 ###
v = getattr(obj,"func") # 根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员。
hasattr(obj,"func") # 根据字符串的形式,去判断对象中是否有该成员。 setattr(obj,"name","ZWQ") # 根据字符串的形式,动态的设置一个成员(内存) delattr(类,"func") # 根据字符串的形式,动态的删除一个成员(内存)
from types import FunctionType
import handler while True:
print("""
系统支持的函数有:
1. f1
2. f2
3. f3
4. f4
5. f5
""")
val = input("请输入要执行的函数:") # val = "f1" # 错误
# handler.val()
if hasattr(handler,val):
func_or_val = getattr(handler,val) # 根据字符串为参数,去模块中寻找与之同名的成员。
if isinstance(func_or_val,FunctionType):
func_or_val()
else:
print(func_or_val)
else:
print('handler中不存在输入的属性名')

getatter 找模块中成员

class Foo(object):

    country = "中国"

    def func(self):
pass v = getattr(Foo,'func') # Foo.func # 根据字符串为参数,去类中寻找与之同名的成员。
print(v) obj = Foo()
v = getattr(obj,"func") # obj.func # 根据字符串为参数,去对象中寻找与之同名的成员。
print(v)

getatter找类或对象中的成员

class Account(object):
func_list = ['login', 'logout', 'register'] def login(self):
"""
登录
:return:
"""
print('登录111') def logout(self):
"""
注销
:return:
"""
print('注销111') def register(self):
"""
注册
:return:
"""
print('注册111') def run(self):
"""
主代码
:return:
"""
print("""
请输入要执行的功能:
1. 登录
2. 注销
3. 注册
""") choice = int(input('请输入要执行的序号:'))
func_name = Account.func_list[choice-1] # func = getattr(Account,func_name) # Account.login
# func(self)
# 执行这个函数要传参数,传self
func = getattr(self, func_name) # self相当于对象可以直接传self相当于self.login
func() obj1 = Account()
obj1.run() obj2 = Account()
obj2.run()

练习题

六,callable(x) 检查x是否是可调用的

def func():
pass class Foo(object):
def __call__(self, *args, **kwargs):
pass def func(self):
pass obj = Foo()
print(callable(func)) #True
print(callable(Foo)) #True
print(callable(obj)) #True
print(callable(obj.func)) #True

面对对象二,super......反射的更多相关文章

  1. JAVA面对对象(三)——Super、static、final关键字

    Super 使用super关键字可以直接调用父类中的构造方法.属性.普通方法 super调用父类构造方法的操作,与this调用构造方法一样,语句必须放在子类构造方法的首行 public class P ...

  2. JAVA面对对象(二)——继承、方法的覆写

    1.继承就是基于已存在的类构造一个新类,继承已存在的类就能复用类的方法和属性,并且能够添加新的方法和属性.也就是子类和父类 2.一个父类可以拥有多个子类,一个子类只允许有一个父类 3.用extends ...

  3. Python - 面对对象(其他相关,异常处理,反射,单例模式,等..)

    目录 Python - 面对对象(其他相关,异常处理,反射,等..) 一.isinstance(obj, cls) 二.issubclass(sub, super) 三.异常处理 1. 异常处理 2. ...

  4. Python学习:16.Python面对对象(三、反射,构造方法,静态字段,静态方法)

    一.构造方法 在使用类创建对象的时候(就是类后面加括号)就自动执行__init__方法. class A: def __init__(self): print('A') class B: def __ ...

  5. js面对对象编程(二):属性和闭包

    上篇博客中解说了一些js对象的基本概念和使用方法.这篇博客解说一下js属性方面的:公有属性.私有属性,特权方法. 假设学过java.公有属性.私有属性,特权方法(即能够訪问和设置私有属性的方法)一定非 ...

  6. python学习——面对对象进阶

    一.isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo: pass a = Foo() print(isins ...

  7. Python - 面对对象(进阶)

    目录 Python - 面对对象(进阶) 类的成员 一. 字段 二. 方法 三. 属性 类的修饰符 类的特殊成员 Python - 面对对象(进阶) 类的成员 一. 字段 字段包括:普通字段和静态字段 ...

  8. 16、python面对对象之类和继承

    前言:本文主要介绍python面对对象中的类和继承,包括类方法.静态方法.只读属性.继承等. 一.类方法 1.类方法定义 使用装饰器@classmethod装饰,且第一个参数必须是当前类对象,该参数名 ...

  9. python面对对象编程----2:__init__

    面对对象编程估计我们最早接触到的就是__init__了,也就是实例的初始化处理过程: 1:来看看最基础的__init__ class Card(object): #抽象类Card,并不用于实例化 de ...

随机推荐

  1. java算法 蓝桥杯 摆花

    问题描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆.通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号.为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时 ...

  2. 高性能Web服务器Nginx的配置与部署研究(12)应用模块之Memcached做文件缓存时压缩引起的问题

    在上一篇文章中,提到的Nginx的Memcached模块应用场景,主要是作为文件缓存.然后就发现了一个问题,当以字节数组方式缓存较大的文件时,缓存数据会被压缩,从而在读取的时候出现问题. (本文欢迎转 ...

  3. fidder 自动保存请求内容

    背景: 因为公司有有app和sdk,这些项目没有对应的接口统计.重构的时候很容易忽略掉.所以对fiddler写了一点代码,能将请求的数据写入到文件或者数据库中.方便统计接口,下次重构的时候,方便统计影 ...

  4. 19-字符切割函数c++模板

    https://www.cnblogs.com/stonebloom-yu/p/6542756.html #include <cstring> #include <cstdio> ...

  5. 启动redis注意事项

    1.需要修改配置文件 redis.conf 三处 a.将bind 127.0.0.0    修改为  bind 0.0.0.0 b.daemonize no      修改为   daemonize ...

  6. 使用Qt Installer Framework制作软件安装包

    概述 Qt Installer Framework(缩写QIF)是Qt官方用于生成软件安装包的工具.包括Qt Creator和Qt Installer Framework自身的安装包都是由这个工具制作 ...

  7. 冲刺NOIP2015提高组复赛模拟试题(五)2.道路修建

    2.道路修建 描述 Description liouzhou_101最悲痛的回忆就是NOI2011的道路修建,当时开了系统堆栈,结果无限RE… 出于某种报复心理,就把那题神奇了一下: 在 Z星球上有N ...

  8. layer使用注意事项

    ajax一定要设置为异步

  9. [SoapUI] 怎样确定一个应答报文的格式是不是标准的JSON

    有一个网站 : http://jsonviewer.stack.hu/ 将Response的文本贴进去,如果是标准的JSON格式,就可以以JSON的view显示出来

  10. python str, list,tuple, dir

    Python3 字符串 字符串是 Python 中最常用的数据类型.我们可以使用引号('或")来创建字符串. 创建字符串很简单,只要为变量分配一个值即可.例如: var1 = 'Hello ...