Python面向对象进阶

一、面向对象那个进阶之反射

  定义:所谓反射就是可以通过字符串来操作Python代码中的变量、函数、甚至类和方法。

    在反射中有四种自省方法,这四种方法适合类和对象(在Python中一切皆对象),下面是四种方法的说明:

      hasattr 判断某一个 变量 是否能够.调用一个名字,返回True或者False

      getattr 直接获取一个变量中的名字的值

      setattr 为一个变量增加或者修改一个属性
      delattr 删除一个变量中的属性或者方法

      反射方法使用说明:

        反射类中的名字

        getattr(类名,'静态属性')

        getattr(类名,'类方法')()
        getattr(类名,'静态方法')() 

# class A:
#     name  = 'Fang'
#     age = 18
# print(getattr(A,'name'))  # getattr获取类中的静态属性名字
         反射对象中的名字

        getattr(对象名,'对象属性')
        getattr(对象名,'方法名')()

#!/usr/bin/python
# -*- encodeing:utf-8 -*-
class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def show(self):
        for key in self.__dict__:
            print(key,self.__dict__[key])
fang = Student('Fang',25)
if hasattr(fang,'name'):   #使用hasattr 判断对象属性能否被调用
    print(getattr(fang,'name'))   #使用getattr获取对象的属性
if hasattr(fang,'show'): # 使用hasattr 判断对象方法能否被调用
    getattr(fang,'show')()  # 使用getattr获取对象的方法
setattr(fang,'sex','')  # 使用setattr添加一个对象属性
getattr(fang,'show')()
delattr(fang,'age')     #使用delattr 删除一个对象的属性
getattr(fang,'show')()
        反射模块中的名字        

        import 模块名
        getattr(模块名,'模块中的变量')
        getattr(模块名,'模块中的函数')()
        getattr(模块名,'模块中的类名')

        反射当前模块中的名字

        import sys
        getattr(sys.modules[__name__],'变量')
        getattr(sys.modules[__name__],'函数')()
        getattr(sys.modules[__name__],'类名')

#!/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')

 

二、双下划线方法

  __str__和__repr__

    _repr__和__str__这两个方法都是用于显示的,__str__是面向用户的,而__repr__面向程序员。

      打印操作会首先尝试__str__和str内置函数(print运行的内部等价形式),它通常应该返回一个友好的显示

      __repr__用于所有其他的环境中:用于交互模式下提示回应以及repr函数,如果没有使用__str__,会使用print和str。它通常应该返回一个编码字符串,可以用来重新创建对象,或者给开发者详细的显示。

当我们想所有环境下都统一显示的话,可以重构__repr__方法;当我们想在不同环境下支持不同的显示,例如终端用户显示使用__str__,而程序员在开发期间则使用底层的__repr__来显示,实际上__str__只是覆盖了__repr__以得到更友好的用户显示

 

#!/usr/bin/python
# -*- encodeing:utf-8 -*-
class Student:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __str__(self):   #添加上__str__时打印类对象就会显示下面的文字
        return '打印类对象时执行我'
    def __repr__(self):   #__repr__属于str的备胎当这个类中没有str这个方法时 程序会直接调用repr这个方法
        return '打印类对象时没有str时执行我'
fang = Student('Fang',25)
print(fang)     #直接打印fang这个类对象,给我们显示的是一个内存地址,看着不是很友好

 

  __del__、__new__、__call__、__hash__

    __del__ 是析构方法。再删除一个对象的时候调用,如果在删除对象的时候,内部存在__del__方法,那么在删除一个对象之前先执行__del__方法中的代码。

    __new__是创建一个对象,在类中先执行new方法,创造出一个对象,然后在把创造出来的对象传递给__init__方法。

    __call__为了将一个类实例当做函数调用,我们需要在类中实现__call__()方法

    __hash__哈希函数的结果就是__hash__方法的返回值,它在一次成的执行过程中哈希值不会发生变化,并且要想作为字典的key或者作为集合的元素,这个对象对应的类必须实现__hash__方法。

#!/usr/bin/python
# -*- encodeing:utf-8 -*-
#del方法
# class A:
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#     def __del__(self):
#         print('删除时调用我')
# a = A('Fang',25)
# print(a)
# del a
# print(a)
#new 方法
# class A:
#     def __init__(self):
#         print('执行init方法')
#     def __new__(cls):
#         print('执行new方法')
#         return  object.__new__(cls)
# a = A()
# print(type(a))
# print(type(A))
# 先执行__new__方法 创造出一个对象
# 然后把创造出来的对象传递给__init__方法
# 会把self自动的返回,被a接收
class A:
    def __call__(self):
        print('执行call了')
A()()

 

三、item系列

  item系列给出了三种方法,__getitem__、__setitem__、__delitem__,用于索引操作,如字典。以上分别表示获取、设置、删除数据

class A:
    def __init__(self,name):
        self.name = name
        self.age = 81
    def __getitem__(self, item):
        return self.__dict__[item]
    def __setitem__(self, key, value):
        self.__dict__[key] = value
    def __delitem__(self, key):
        del self.__dict__[key]
a = A('alex')
# print(a['name'])  # 对应了类中一个方法的语法
# a.name
# print(a['age'])  # 对应了类中一个方法的语法
# a.age
# 增加 和 修改一个属性
a['sex'] = '不详'
# a.sex = '不详'
print(a.__dict__)
# print(a.sex)
# print(a['sex'])
a['sex'] = ''
print(a.__dict__)
del a['sex']
print(a.__dict__)

 

posted @ 2018-03-13 16:15  曹艳飞  阅读(355)  评论(0编辑  收藏  举报