xingyemdd

导航

 

一、反射

1、什么是反射

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

2 、python面向对象中的反射

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

类名 ——反射 静态属性
对象名 ——反射 对象属性 和 方法
模块  ——反射模块中的名字
反射 ——自己所在文件中的名字

3、使用说明

首先 使用getattr取获取一个名字,如果在这个对象的命名空间中没有这个名字 会报错;
getattr的反射好伴侣 hasattr 判断在这个对象的命名空间中没有这个名字 存在返回True 否则False;
如果使用getattr取获取一个方法,那么只能拿到这个方法的内存地址 加上括号就是执行,当然,括号里的参数可以照传不误;
如果getattr获取一个属性,那么直接使用反射就可以获取到值。

模块就是一个py文件,pyi代表是内置模块;
所谓的模块导入 就是执行了这个文件而已。

4、四个可以实现自省的函数:hasattr、getattr、setattr、delattr

# 1)四个方法的使用示例
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'))  # >>>True
print(hasattr(obj, 'say_hi'))  # >>>True

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

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

# 设置属性
setattr(obj, 'sb', True)
setattr(obj, 'show_name', lambda self: self.name + 'sb')
print(
    obj.__dict__)  # >>>{'name': 'egon', 'age': 73, 'sb': True, 'show_name': <function <lambda> at 0x00000292BAE05F28>}
print(obj.show_name(obj))  # >>>egonsb

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

print(obj.__dict__)  # >>>{'name': 'egon', 'sb': True}
#2)类也是对象
class Foo(object):
    staticField = "old boy"

    def __init__(self):
        self.name = 'wupeiqi'

    def func(self):
        return 'func'

    @staticmethod
    def bar():
        return 'bar'


print(getattr(Foo, 'staticField'))
print(getattr(Foo, 'func'))
print(getattr(Foo, 'bar'))

# 执行结果
# old boy
# <function Foo.func at 0x000001A8F4739378>
# <function Foo.bar at 0x000001A8F4739400>
# 3)反射当前模块的成员
import sys

def s1():
    print('s1')

def s2():
    print('s2')

this_module = sys.modules[__name__]

print(hasattr(this_module, 's1'))#>>>True
getattr(this_module, 's2')()#>>>s2
# 4)示例
class Person:
    role = 'Person'  # 静态属性

    def __init__(self, name):
        self.name = name  # 对象属性

    def eat(self): print('eating')

    def drink(self): print('drinking')

    def play(self): print('playing')

    def sleep(self): print('sleepping')


alex = Person('alex')
alex.name
print(getattr(alex, 'name'))  # >>>alex
print(getattr(Person, 'role'))  # >>>Person

while True:
    inp = input('>>>')
    if hasattr(alex, inp):
        getattr(alex, inp)()
# 执行结果:
# >>>eat
# eating
# >>>drink
# drinking
# >>>play
# playing
# >>>sleep
# sleepping
# >>>111
# >>>
# 5)反射当前模块成员
# mymodule.py
# money = 100
# def func1():
#     print('func1')
#
# def func2():
#     print('func2')
#
# class Manager:
#     def eat(self):
#         print('eating')

import mymodule
import time

mymodule.func1()#>>>func1
time.sleep(0.5)
print(mymodule.money)#>>>100
getattr(mymodule,'func1')()#>>>func1
print(getattr(mymodule,'money'))#>>>100
getattr(time,'sleep')(1)

Manager = getattr(mymodule,'Manager')#拿到一个类的内存地址
a = Manager()
a.eat()#>>>eating

value = '123'
import sys
print(sys.modules)
#>>>{'builtins': <module 'builtins' (built-in)>, 'sys': <module 'sys' (built-in)>, '_frozen_importlib': <module '_frozen_importlib' (frozen)>, '_imp': <module '_imp' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_thread': <module '_thread' (built-in)>, '_weakref': <module '_weakref' (built-in)>, '_frozen_importlib_external': <module '_frozen_importlib_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'nt': <module 'nt' (built-in)>, 'winreg': <module 'winreg' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, 'encodings': <module 'encodings' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\__init__.py'>, 'codecs': <module 'codecs' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\aliases.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\utf_8.py'>, '_signal': <module '_signal' (built-in)>, '__main__': <module '__main__' from 'C:/Users/28163/Desktop/老男孩教育-Python21期/day07/day7视频与笔记/day7笔记/9.反射.py'>, 'encodings.latin_1': <module 'encodings.latin_1' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\latin_1.py'>, 'io': <module 'io' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\io.py'>, 'abc': <module 'abc' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\abc.py'>, '_weakrefset': <module '_weakrefset' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_weakrefset.py'>, 'site': <module 'site' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\site.py'>, 'os': <module 'os' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\os.py'>, 'errno': <module 'errno' (built-in)>, 'stat': <module 'stat' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\stat.py'>, '_stat': <module '_stat' (built-in)>, 'ntpath': <module 'ntpath' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\ntpath.py'>, 'genericpath': <module 'genericpath' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\genericpath.py'>, 'os.path': <module 'ntpath' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\ntpath.py'>, '_collections_abc': <module '_collections_abc' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_sitebuiltins.py'>, '_bootlocale': <module '_bootlocale' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\_bootlocale.py'>, '_locale': <module '_locale' (built-in)>, 'encodings.gbk': <module 'encodings.gbk' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\gbk.py'>, '_codecs_cn': <module '_codecs_cn' (built-in)>, '_multibytecodec': <module '_multibytecodec' (built-in)>, 'sysconfig': <module 'sysconfig' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\sysconfig.py'>, 'encodings.cp437': <module 'encodings.cp437' from 'C:\\Users\\28163\\AppData\\Local\\Programs\\Python\\Python36\\lib\\encodings\\cp437.py'>, 'sitecustomize': <module 'sitecustomize' from 'C:\\Program Files\\JetBrains\\PyCharm 2017.3.4\\helpers\\pycharm_matplotlib_backend\\sitecustomize.py'>, 'mymodule': <module 'mymodule' from 'C:\\Users\\28163\\Desktop\\老男孩教育-Python21期\\day07\\day7视频与笔记\\day7笔记\\mymodule.py'>, 'time': <module 'time' (built-in)>}
print(sys.modules['__main__'])
#>>><module '__main__' from 'C:/Users/28163/Desktop/老男孩教育-Python21期/day07/day7视频与笔记/day7笔记/9.反射.py'>
print(getattr(sys.modules['__main__'],'value'))#>>>123   反射自己模块当中的名字
# 6)示例
class Manager:
    def __init__(self, name):
        self.name = name

    def create_course(self):
        pass

class Teacher:
    def __init__(self, name):
        self.name = name

    def list_student(self):
        pass

class Student:
    def __init__(self, name):
        self.name = name

    def create_course(self):
        pass


a = Student('a')
a.age = 19
setattr(a, 'age', 25)
print(a.__dict__)  # >>>{'name': 'a', 'age': 25}
print(a.age)  # >>>25
import sys

# login 先进行登录
# 输入name,pwd 与文件内容比对,然后找到对应身份的类

id = 'Manager'
if hasattr(sys.modules['__main__'], id):
    obj = getattr(sys.modules['__main__'], id)(name, pwd)

 二、面向对象进阶

1、isinstance和issubclass

# 1)isinstance(obj,cls)检查是否obj是否是类 cls 的对象
class Foo(object):
    pass

obj = Foo()

print(isinstance(obj, Foo))  # >>>True

# 2)issubclass(sub, super)检查sub类是否是 super 类的派生类
class Foo(object):
    pass

class Bar(Foo):
    pass

print(issubclass(Bar, Foo))  # >>>True

2、__new__

1)__new__、__init__

# __new__    构造方法 创建一个对象
# __init__   初始化方法
# 先执行new方法,object.new()   再执行init
class Foo:
    def __new__(cls, *args, **kwargs):
        print('执行我啦')
        obj = object.__new__(cls)
        print(obj)
        return obj

    def __init__(self):
        print('222222222', self)

Foo()

# 执行结果:
# >>>执行我啦
# >>><__main__.Foo object at 0x000002C2FB913A90>
# >>>222222222 <__main__.Foo object at 0x000002C2FB913A90>

# 执行过程:
# Foo()  --> python解释器接收到你的python代码
# python解释器替你去做了很多操作(翻译成C语言的字节码,将C语言的字节码解释成 机器码 让CPU去执行)
# 包括 主动帮助你 调用 new方法 去创造一个对象 —— 开辟内存空间 —— python语言封装了开辟内存的工作
# object的new方法里 —— 帮你创造了对象
# 调用init用到的self参数 就是new帮你创造的对象

2)单例模式

# 单例模式 : 是一种设计模式  某一个类 只有一个实例
class Person:
    __isinstance = None

    def __new__(cls, *args, **kwargs):
        if not cls.__isinstance:
            obj = object.__new__(cls)
            cls.__isinstance = obj
        return cls.__isinstance

    def __init__(self, name):
        self.name = name

alex = Person('alex')
alex.age = 18
egon = Person('egon')
print(egon.age)
print(id(alex))
print(id(egon))
print(alex.name)
print(egon.name)

# 执行结果:
# 18
# 2669030687800
# 2669030687800
# egon
# egon

3、__str__、__repr__、__format__

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

自定制格式化字符串__format__

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)

# 执行结果
# >>>from repr:  School(oldboy1,北京)
# >>>from str:  (oldboy1,北京)
# >>>(oldboy1,北京)

'''
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'))

# 执行结果
# >>>oldboy1-北京-私立
# >>>私立:oldboy1:北京
# >>>私立/北京/oldboy1
# >>>oldboy1-北京-私立
class B:
    def __str__(self):
        return 'str : class B'

    def __repr__(self):
        return 'repr : class B'

b = B()
print('%s' % b)
print('%r' % b)

# 执行结果
# >>>ostr : class B
# >>>orepr : class B

4、__del__

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

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

class Foo:

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

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

# 输出结果
# >>>执行我啦
# >>>------->

5、item系列(__getitem__、__setitem__、__delitem__)

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 obj.key时,我执行
del f1['age']  # >>>del obj[key]时,我执行
f1['name'] = 'alex'
print(f1.__dict__)  # >>>{'name': 'alex'}

6、__call__

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

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

class Foo:

    def __init__(self):
        pass

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

obj = Foo()  # 执行 __init__
obj()  # 执行 __call__
# 输出结果>>>__call__

7、__len__

class A:
    def __init__(self):
        self.a = 1
        self.b = 2

    def __len__(self):
        return len(self.__dict__)

a = A()
print(len(a))  # >>>2

8、__hash__

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))  # >>>1060108502313640553

9、__eq__

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)  # >>>True

面试题:

#实例化n个对象 84 个
#对84个对象进行去重
# 如果两个对象的姓名和性别相同,我就认为是相同的对象

class Person:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __hash__(self):
        return hash(self.name + self.sex)

    def __eq__(self, other):
        if self.name == other.name and self.sex == other.sex: return True


p_lst = []
for i in range(84):
    p_lst.append(Person('egon', i, 'male'))

print(p_lst)
print(set(p_lst))

 

posted on 2018-05-23 23:23  xingyemdd  阅读(170)  评论(0编辑  收藏  举报