python全栈开发从入门到放弃之面向对象反射

时间:2021-12-09 00:00:43

1、classmethod、staticmethod方法

classmethod类方法默认参数cls,可以直接用类名调用,可以与类属性交互

#student文件内容
宝宝,男
博博,女
海娇,男
海燕,女
海东,男
海峰,男





class Student:
f
= open('student', encoding='utf-8')
def __init__(self):
pass

def func(self):
pass

@classmethod #类方法:默认参数cls,可以直接用类名调用,可以与类属性交互
def show_student_info_class(cls):
for line in cls.f:
name, sex
= line.strip().split(',')
print(name, sex)
@staticmethod #静态方法 : 让类里的方法直接被类调用,就像正常的函数一样
def show_student_info_static():
f
= open('student', encoding='utf-8')
for line in f:
name, sex
= line.strip().split(',')
print(name, sex)
print(Student.show_student_info_class())
print(Student.show_student_info_static())

'''
运行结果:
宝宝 男
博博 女
海娇 男
海燕 女
海东 男
海峰 男
None
宝宝 男
博博 女
海娇 男
海燕 女
海东 男
海峰 男
None
'''

总结:

相同:都可以直接被类调用,不需要实例化,也都可以实例化然后再调用
不同:
类方法必须有一个cls参数表示这个类,可以使用类属性
静态方法不需要,静态方法不能直接使用
绑定方法
非绑定方法
普通方法 默认有一个self对象传进来,并且只能被对象调用——绑定到对象
类方法 默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类
静态方法 没有默认参数,并且可以被类和对象(不推荐)调用——非绑定

2.isinstance、issubclass

isinstance

判断一个对象是不是这个类的对象,传两个参数(对象,类)
class Foo:
pass

class Son(Foo):
pass

s
= Son()
#判断一个对象是不是这个类的对象,传两个参数(对象,类)
print(isinstance(s,Son))
print(isinstance(s,Foo))
print(type(s) is Son)
print(type(s) is Foo)

issubclass

class Foo:
pass

class Son(Foo):
pass

s
= Son()

#判断一个类是不是另一类的子类,传两个参数(子类,父类)
print(issubclass(Son,Foo))
print(issubclass(Son,object))
print(issubclass(Foo,object))
print(issubclass(int,object))

'''
输出结果:
True
True
True
True
'''

一、反射

 

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

 

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

四个可以实现自省的函数

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

常用:
hasattr
getattr

不常用:
setattr
delattr
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
hasattr

class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
print(hasattr(egg,'name')) #如果存在则返回一个布尔值
hasattr
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
print(getattr(egg,'name')) #根据后面的参数相当于key输出结果
getattr
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
if hasattr(egg,'func'): #返回bool
Foo_func = getattr(egg,'func') #如果存在这个方法或者属性,就返回属性值或者方法的内存地址
#如果不存在,报错,因此要配合hasattr使用
Foo_func()
'''
输出结果:
123
'''
hasattr和getattr组合用法
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
setattr(egg,
'sex','属性值') #给类添加一个变量和属性值
print(egg.sex)

'''
输出结果:
属性值
'''
setattr
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()
#常用:

def show_name(self):
print(self.name + ' sb')
setattr(egg,
'sh_name',show_name)
egg.sh_name(egg)
show_name(egg)
egg.sh_name()

'''
输出结果:
egon sb

'''
setattr用法
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self):
self.name
= 'egon'
self.age
= 73

def func(self):
print(123)

egg
= Foo()

delattr
delattr(egg,
'name') #删除
print(egg.name) #删除了之后会找不到会报错
delattr
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
f
= '类的静态变量'
def __init__(self,name,age):
self.name
=name
self.age
=age

def say_hi(self):
print('hi,%s'%self.name)

obj
=Foo('egon',73)

#检测是否含有某属性
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))

#获取属性
n=getattr(obj,'name')
print(n)
func
=getattr(obj,'say_hi')
func()

print(getattr(obj,'aaaaaaaa','不存在啊')) #报错

#设置属性
setattr(obj,'sb',True)
setattr(obj,
'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))

#删除属性
delattr(obj,'age')
delattr(obj,
'show_name')
delattr(obj,
'show_name111')#不存在,则报错

print(obj.__dict__)
四个的用法

类也是对象

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
f
= 123 #类变量
@classmethod
def class_method_demo(cls):
print('class_method_demo')
@staticmethod
def static_method_demo():
print('static_method_demo')
# if hasattr(Foo,'f'):
#
print(getattr(Foo,'f'))
print(hasattr(Foo,'class_method_demo'))
method
= getattr(Foo,'class_method_demo')
method()
print(hasattr(Foo,'static_method_demo'))
method2
= getattr(Foo,'static_method_demo')
method2()
#类也是对象
类对象

在其他模块的反射

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
#my_module文件内容
def test():
print('test')


import my_module
print(hasattr(my_module,'test')) #返回一个布尔值
func_test = getattr(my_module,'test') #反射给一个变量
func_test() #然后变量调用执行文件内容
getattr(my_module,'test')() #还可以这种用法
'''
输出结果:
True
test
test
'''
View Code

在本模块的反射

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
def demo1():
print('demo1')

import sys
print(__name__) #'__main__'
print(sys.modules)
#'__main__': <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'>
module_obj =sys.modules[__name__] #sys.modules['__main__']
#
module_obj : <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'>
print(module_obj)
print(hasattr(module_obj,'demo1'))
getattr(module_obj,
'demo1')()
# #在本模块中应用反射
本模块的反射
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
#对象
#

#
模块 : 本模块和导入的模块

def register():
print('register')

def login():
pass

def show_shoppinglst():
pass
#
print('注册,登录')
ret
= input('欢迎,请输入您要做的操作: ')
import sys
# print(sys.modules)
my_module = sys.modules[__name__]
if hasattr(my_module,ret):
getattr(my_module,ret)()
使用

 

自定义格式字符串

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
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'))
View Code

__str__和__repr__

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self,name):
self.name
= name
def __str__(self):
return '%s obj info in str'%self.name
def __repr__(self):
return 'obj info in repr'

f
= Foo('egon')
# print(f)
print('%s'%f)
print('%r'%f)
print(repr(f)) # f.__repr__()
print(str(f))
'''
输出结果:
egon obj info in str
obj info in repr
obj info in repr
egon obj info in str
'''
View Code

总结:

#当打印一个对象的时候,如果实现了str,打印中的返回值
#当str没有被实现的时候,就会调用repr方法
#但是当你用字符串格式化的时候 %s和%r会分别去调用__str__和__repr__
#不管是在字符串格式化的时候还是在打印对象的时候,repr方法都可以作为str方法的替补
#但反之不行
#用于友好的表示对象。如果str和repr方法你只能实现一个:先实现repr

__del__

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

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __del__(self):
print('执行我啦')

f
= Foo()
print(123)
print(123)
print(123)
print(123)
print(123) #如果没有执行会在程序结束的时候执行

'''
123
123
123
123
123
执行我啦
'''


class Foo:
def __del__(self):
print('执行我啦')

f
= Foo()
print(123)
print(123)
del f #当如果在中间执行了就会直接执行不会再程序结束时候执行
print(123)
print(123)
print(123)

'''
123
123
执行我啦
123
123
123
'''
__del__

item系列

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:
def __init__(self,name):
self.name
=name

def __getitem__(self, item):
print(self.__dict__[item])

def __setitem__(self, key, value):
self.
__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]时,我执行')
self.
__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key时,我执行')
self.
__dict__.pop(item)

f1
=Foo('sb')
f1[
'age']=18
f1[
'age1']=19
del f1.age1
del f1['age']
f1[
'name']='alex'
print(f1.__dict__)
View Code

 

随笔- 29  文章- 55  评论- 58   

python之路——面向对象进阶

 

阅读目录

回到顶部

isinstance和issubclass

isinstance(obj,cls)检查是否obj是否是类 cls 的对象

class Foo(object):
pass

obj = Foo()

sinstance(obj, Foo)

issubclass(sub, super)检查sub类是否是 super 类的派生类 

python全栈开发从入门到放弃之面向对象反射
class Foo(object):
pass

class Bar(Foo):
pass

issubclass(Bar, Foo)
python全栈开发从入门到放弃之面向对象反射

 

回到顶部

反射

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

 

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

四个可以实现自省的函数

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

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
def hasattr(*args, **kwargs): # real signature unknown
"""
Return whether the object has an attribute with the given name.

This is done by calling getattr(obj, name) and catching AttributeError.
"""
pass
python全栈开发从入门到放弃之面向对象反射
python全栈开发从入门到放弃之面向对象反射 getattrpython全栈开发从入门到放弃之面向对象反射 setattrpython全栈开发从入门到放弃之面向对象反射 delattrpython全栈开发从入门到放弃之面向对象反射 四个方法的使用演示

 

python全栈开发从入门到放弃之面向对象反射 类也是对象

 

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys


def s1():
print 's1'


def s2():
print 's2'


this_module = sys.modules[__name__]

hasattr(this_module, 's1')
getattr(this_module, 's2')
python全栈开发从入门到放弃之面向对象反射

导入其他模块,利用反射查找该模块是否存在某个方法

python全栈开发从入门到放弃之面向对象反射 View Codepython全栈开发从入门到放弃之面向对象反射 View Code

 

回到顶部

__str__和__repr__

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

自定制格式化字符串__format__

python全栈开发从入门到放弃之面向对象反射 View Codepython全栈开发从入门到放弃之面向对象反射 %s和%r

 

回到顶部

__del__

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

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Foo:

def __del__(self):
print('执行我啦')

f1=Foo()
del f1
print('------->')

#输出结果
执行我啦
------->
python全栈开发从入门到放弃之面向对象反射

 

 

回到顶部

item系列

__getitem__\__setitem__\__delitem__

python全栈开发从入门到放弃之面向对象反射 View Code 

__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)
python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig
= super(Singleton, cls)
cls._instance
= orig.__new__(cls, *args, **kw)
return cls._instance

one
= Singleton()
two
= Singleton()

two.a
= 3
print(one.a)
# 3
#
one和two完全相同,可以用id(), ==, is检测
print(id(one))
# 29097904
print(id(two))
# 29097904
print(one == two)
# True
print(one is two)
单例模式

__call__

对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

class Foo:

def __init__(self):
pass

def __call__(self, *args, **kwargs):

print('__call__')


obj
= Foo() # 执行 __init__
obj() # 执行 __call__

__len__

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class A:
def __init__(self):
self.a
= 1
self.b
= 2

def __len__(self):
return len(self.__dict__)
a
= A()
print(len(a))
View Code

__hash__

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class A:
def __init__(self):
self.a
= 1
self.b
= 2

def __hash__(self):
return hash(str(self.a)+str(self.b))
a
= A()
print(hash(a))
View Code

__eq__

python全栈开发从入门到放弃之面向对象反射python全栈开发从入门到放弃之面向对象反射
class A:
def __init__(self):
self.a
= 1
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 == b)
View Code