方法&函数区别,反射

主要内容:

  • 1. isinstance, type, issubclass
  • 2. 方法和函数的区别
  • 3. 反射(重点)

1. isinstance, type, issubclass

(1) issubclass(xxx,yyy) 这个内置函数可以帮我们判断xxx类是否是yyy类型的子类.

class Base:
    pass
class Foo(Base):
    pass
class Bar(Foo):
    pass
print(issubclass(Bar, Foo))    #True
print(issubclass(Foo, Bar))    #False
print(issubclass(Bar, Base))   #True

(2) type

      type(obj) 表示查看obj是由哪个类创建的

class Foo:
    pass
obj = Foo()
print(obj, type(obj))   # 查看obj的类

      判断xxx是否是xxx数据类型的 

class Boy:
    pass
class Girl:
    pass
# 统计传进来的男生和女生分别有多少
def func(*args):
    b = 0
    g = 0
    for obj in args:
        if type(obj) == Boy:
            b += 1
        elif type(obj) == Girl:
            g += 1
    return b, g
ret = func(Boy(), Girl(), Girl(), Girl(), Boy(), Boy(), Girl())
print(ret)                    # (3, 4)

在进行计算的时,先判断好要计算的数据类型必须是int或者float. 这样的计算才有意义

def add(a, b):
    if (type(a) == int or type(a) == float) and (type(b) == int or type(b) == float):
        return a + b
    else:
        print("我要报错")

(3) isinstance(xxx,yyy):  判断xxx是yyy类型的数据. 但是isinstance没有type那么精准

class Base:
    pass
class Foo(Base):
    pass
class Bar(Foo):
    pass
print(isinstance(Foo(), Foo))      # True 
print(isinstance(Foo(), Base))     # True 
print(isinstance(Foo(), Bar))      # False

  isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)

2. 方法和函数的区别

2.1 在类外边定义的函数一定是函数

def func():
    print("你猜猜看")
print(func)                     #<function func at 0x000002819F1B6048>

2.2 写在类中的函数

class Foo:
    # 实例方法: 对象.方法  方法    类名.方法  函数
    def func(self):
        print("这里是什么呢!")
obj = Foo()
print(obj.func)                   #绑定的方法<bound method Foo.func of <__main__.Foo object at 0x00000217422E7978>>

Foo.func(obj) print(Foo.func) #类名直接调用就是方法 <function Foo.func at 0x000002BCB0528A60>

注: 如果通过对象方法,那么self 它会自动帮你传递, 如果使用类名来调用,self就不会帮你传递

2.3 类中的类方法,静态方法

class Foo:
    @staticmethod
    def static_method():
        pass

    @classmethod  # 都是方法
    def class_method(cls):  # 类对象的内容
        pass

    @property  # 神马都不是. 变量
    def age(self):
        return 10
f = Foo()
# print(f.static_method)               #<function Foo.static_method at 0x000001ACF90D8A60>
# print(Foo.static_method)             #<function Foo.static_method at 0x0000012304688A60>

# print(f.class_method)                  #<bound method Foo.class_method of <class '__main__.Foo'>>
# print(Foo.class_method)                #<bound method Foo.class_method of <class '__main__.Foo'>>

print(f.age)                             #10
print (Foo.age)                          #   <property object at 0x000002B3197FB7C8>

2.4 通过 types中的FunctionType和MethodType可以区分当前内容是方法还是函数,

注: 判断是方法还是函数

from types import MethodType,FunctionType
def check(arg):
    '''
    判断arg是函数则打印1,arg是方法则打印2
    :param arg
    '''
    if isinstance(arg,MethodType):
        print(2)
    elif isinstance(arg,FunctionType):
        print(1)
    else:
        print('不认识')
        
def func():
    pass
class Foo(object):
    def display(self):
        pass
check(func)                            #1
check(Foo.display)                     #1
check(Foo().display)                   #2

2.5 练习

class RoleConfig(object):
    def f1(self,arg):
        print('f1',arg)
    def f2(self,arg):
        print('f2',arg)
    list_display =[f1,f2]

# obj = RoleConfig()
for item in RoleConfig.list_display:
    item(RoleConfig()
class RoleConfig(object):

    def f1(self, arg):
        print('f1', arg)

    def f2(self, arg):
        print('f2', arg)

    def f3(self, arg):
        print('f3', arg)

#静态字段 list_display
= [f1, f2] def get_list_display(self): self.list_display.insert(0, RoleConfig.f3) return self.list_display obj1 = RoleConfig() for item in obj1.get_list_display(): item(obj1, 2) obj2 = RoleConfig() for item in obj2.get_list_display(): item(obj2, 6)
class RoleConfig(object):

    def f1(self, arg):
        print('f1', arg)

    def f2(self, arg):
        print('f2', arg)

    def f3(self, arg):
        print('f3', arg)

    list_display = [f1, f2]

    def get_list_display(self):
        v = []
        v.extend(self.list_display)
        v.insert(0, RoleConfig.f3)
        return v

obj1 = RoleConfig()
for item in obj1.get_list_display():
    item(obj1, 2)

obj2 = RoleConfig()
for item in obj2.get_list_display():
    item(obj2, 6)

小结:

  •  类方法. 不论任何情况, 都是方法.
  •  静态方法, 不论任何情况. 都是函数
  •  实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数. 

3.反射

3.1 引入

一个需求, 说, 有个大牛, 写一堆特别牛B的代码. 然后放在一个py文件里(模块),这时, 你想用这个大牛写的东西,但是呢. 你首先得知道大牛写的这些代码都是干什么用的. 那就需要你把大牛写的每一个函数跑一下. 摘⼀摘自己想用的内容. 来咱们模拟 这样的需求,首先, 大牛给出一个模块. 

def chi():
    print ("大牛一次吃一桶")
def he():
    print ("大牛一顿喝100杯水")
def la():
    print ("大牛不用拉")
def sleep():
    print("大牛一睡睡一年")
name = "大牛"
import master
while 1 :
    print('''大牛写了很多东西
    chi
    he
    la
    sleep
''')
    val = input("请输入你要测试的功能")
#判读 master这个py 文件中是否有你想要的的功能
if hasattr(master,val):
     #获取这个功能 (从xxx对象中或者模块中找到xxx(字符串)功能,变量) attr
= getattr(master,val)
#判断这个东西是否可以被调用 if callable(attr): attr() else: print(attr) else: print("没有这个功能")

上面有两个函数:一个是getattr(),hasattr()

  • getattr()用来获取信息.
  • hasattr()用来判断xxx中是否包含了xxx功能,. 

3.2 反射的概述

(1)反射的定义(什么是反射机制):

  • 反射就是通过字符串的形式,导入模块;
  • 通过字符串的形式,去模块寻找指定函数,并执行。
  • 利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员,一种基于字符串的事件驱动

3.3 反射的使用

3.3.1面向对象中的反射

(1)hasattr (xxx, ooo)  (判断xxx中是含有ooo)

class Movie(object):
    def __init__(self,name):
        self.name  = name

    def release(self):
        print('%s正在放映'%self.name)

movie =Movie('大话西游')
#hasattr 返回的是True / False
print(hasattr(movie,'name')) #True 存在name这个属性 print(hasattr(movie,'release')) #True 存在release这个方法 print(hasattr(movie,'place')) #False 不存在产地place这个属性

(2)getattr

class Movie(object):
    language = '国语'
    def __init__(self,name):
        self.name  = name

    def release(self):
        print('%s正在放映'%self.name)

movie =Movie('大话西游')

#从类中获取属性
attr = getattr(Movie,'language')
print(attr)     #国语
#获取对象的属性
attr1 = getattr(movie,'name')
print(attr1)    #大话西游(获取到的是name的内存地址)

#获取对象可执行的方法
attr2 = getattr(movie,'release')
attr2()         # 大话西游正在放映
print(attr2)    #<bound method Movie.release of <__main__.Movie object at 0x00000215EDF585F8>>

 注;

关于 getattr(object,'xxxx' 'not find')  第三个参数意思是当从object对象中获取不到xxx时候返回  第三个参数

(3)setattr()

class Movie(object):
    language = '国语'
    def __init__(self,name):
        self.name  = name

    def release(self):
        print('%s正在放映'%self.name)

movie =Movie('大话西游')
setattr(movie,'name','少林足球')   #可以动态的给对象设置属性
print(movie.name)                 #少林足球
setattr(movie,'place','内地')     #可以给对象设置属性和值
print(movie.place)                # 内地

(4)delattr()

class Movie(object):
    language = '国语'
    def __init__(self,name):
        self.name  = name

    def release(self):
        print('%s正在放映'%self.name)

movie =Movie('大话西游')
                 #少林足球
setattr(movie,'place','内地')     #可以给对象设置属性和值
print(movie.place)                # 内地

delattr(movie,'place')
print(movie.place)                #已删除

反射共有4个函数:

  • 1. hasattr(obj, str) 判断obj中是否包含str成员
  • 2. getattr(obj,str) 从obj中获取str成员
  • 3. setattr(obj, str, value) 把obj中的str成员设置成value. 注意. 这里的value可以是值, 也可以是函数或者方法
  • 4. delattr(obj, str) 把obj中的str成员删除掉           

注意, 以上操作都是在内存中进行的. 并不会影响你的源代码

原文地址:https://www.cnblogs.com/wcx666/p/9719902.html