一、应用反射操作模块中的类

  流程:导入模块——》调用模块中的类——》创建类对象——》调用类对象的成员——》操作成员

复制代码
#-------------------------------使用反射,操作模块中的类-----------------
#
# 1、导入模块
module = __import__('file.py',fromlist=True)  # fromlist=True,文件有迭代
# 2、调用模块中的类
import_class = getattr(module,'class_name')
# 3、根据类创建对象
obj = import_class('lucy')  # self.name = 'lucy'
# 4、调用对象的成员
ret = getattr(obj,'name')
# 5、使用调用元素:字段或方法
print(ret)
View Code
复制代码

  二、访问类和对象的成员

  (一)各成员及访问规范:

    使用类名访问:静态字段(每个对象都有一份)、静态方法(无需使用对象封装的内容)、类方法。

    使用对象访问:普通字段(每个对象都不同的数据)、普通方法(使用对象中的数据)、特性。

复制代码
class Cat():
    ty = 'annimal'       # 静态字段

    def __init__(self,name):
        self.n = name     # 普通字段

    @staticmethod
    def sf(words):
        print(words)                # 静态方法,不含参数self,有装饰器staticmethod

    @classmethod
    def cf(cls,word):               # 类方法,含有参数cls,有装饰器classmethod
        cls.sf(word)

    def f(self):
        print('普通方法')          # 普通方法,含参数self

    @property                       # 特性方法,除self外不含参数,有装饰器property
    def pf(self):          # 获取特性,将方法伪装成特性
        return self.ty
    @pf.setter
    def pf(self,value):    # 设置特性,带有设置参数
        print(value)
        self.ty = value
        return self.ty


# 使用类名访问:静态字段、静态方法、类方法
print(Cat.ty)               # annimal
Cat.sf('staticmethod')     # staticmethod
Cat.cf('classmethod')      # classmethod
#
# 使用对象访问:普通字段、普通方法、特性方法
c = Cat('miao')
print(c.n)              # miao
# 普通方法调用时,后面加()
c.f()                   # 普通方法
# 特性方法调用时,后面不用加()
ret1 = c.pf    # 获取特性
print(ret1)              # annimal
c.pf = '123'  # 设置特性
ret2 = c.pf
print(ret2)              # 123
View Code
复制代码

  (二)成员修饰符

    关于类的成员,有些公共内容可以外部用、有些私有内容只可以内部用,使用成员修饰符(两个下划线__)标识。

    私有内容,通常仅供内部使用,外部不能直接调用。但是可以间接调用,也可以使用固定语法强制使用。

复制代码
# #---------------------------成员修饰符---------------------------
# 关于类的成员,有些内部可以用,有些外部可以用,需要用成员修饰符:两个下划线__。

class A():
    ty = 'words'   # 不加修饰符,表示是公有的
    __ty = 'A'      # 加修饰符,表示是私有的
    def __init__(self):
        self.age = 4
        self.__age = 5
    def f_A(self):
        print(self.__ty)   # 私有内容仅可以自己使用,子类也访问不了
        print(self.__age)
    def f__ty(self):    # 私有内容,外部不能之间访问,但是可以间接访问
        return self.__ty


print(A.ty)      # 公有内容,可以访问
# print(A.__ty)  # 报错,私有内容不可以访问

a = A()
print(a.age)    # 公有内容,可以访问
a.f_A()         # 私有内容可以间接访问
print(a.f__ty())

# 强制访问私有内容,使用固定语法:
print(a._A__ty)
# ----------------------------------------------------------
View Code
复制代码

  三、类的特殊成员

  常见的特殊成员有:__doc__、__module__\__class__、__dict__、__init__()、__del__()、__call__()、__str__()、__getitem__()\__setitem__()\__delitem__()、__iter__()等。

复制代码
# 1、__doc__ 类的注释
class F00:
    '''
    这是类FOO的注释
    '''
    def f(self):
        pass

print(F00.__doc__)  # 这是类FOO的注释

a = F00()
print(a.__doc__)    # 这是类FOO的注释

# # 2、__moudle__、__class__ 当前操作在哪个模块、什么类
class F00:
    def f(self):
        pass

a = F00()
print(a.__class__)  # <class '__main__.F00'>
print(a.__module__)  # __main__

# 3、__init__() 构造方法,根据类创建对象时,自动执行
class F00:
    def __init__(self,arg):
        self.name = arg
        print(self.name)

a = F00('lucy')     # outputP:  lucy

# 4、__del__() 析构方法,对象删除时,自动执行
class F00:
    def __init__(self):
        pass
    def __del__(self):
        print('对象已删除')

a = F00()
del a  # output: 对象已删除

# 5、__call__()  对象后面加括号,触发执行
# 类名后面加(),触发执行__init__();对象后面加(),触发执行__call__()。
class F00:
    def __init__(self):
        print('我是__init__()')
    def __call__(self):
        print('我是__call__()')

a = F00()   # 我是__init__()
a()         # 我是__call__()
# 上面两句,等同于:
F00()()

# 6、__dict__ 类或对象中的成员
class F00:
    country = 'china'
    def __init__(self,arg):
        self.province = arg
    def f(self):
        pass
# 对象中成员
a = F00('anhui')
print(a.__dict__) # {'province': 'anhui'}

# 类中成员
c_dict = F00.__dict__
print(c_dict)
for key,value in c_dict.items():
    print(key,':',value)

7、__str__()  打印对象时,输出返回值
class F00:
    def __init__(self):
        pass
    def __str__(self):
        return  '打印时触发:__str__'

a = F00()
print(a)   # 打印时触发:__str__

# 8、__getitem__、__setitem__、__delitem__ 用于索引操作,如字典。
class F00:
    def __getitem__(self, item):
        print('__getitem__',item)
    def __setitem__(self, key, value):
        print('__setitem__',key,value)
    def __delitem__(self, key):
        print('__delitem__',key)

obj = F00()
result = obj['k1':1]   # __getitem__ slice('k1', 1, None)
obj['k2'] = 2          # __setitem__ k2 2
del obj['k1']          # __delitem__ k1

9、__iter__() 迭代循环(如for循环)时触发
实例一
class F00:
    def __iter__(self):
        yield 1
        yield 2
a = F00()
for i in a :
    print(i)
# 实例二
class F00:
    def __init__(self,arg):
        self.list = arg
    def __iter__(self):
        return iter(self.list)

a = F00([1,2,3,4])
for i in a :
    print(i)

10、__new____metaclass__ 指定创建类
View Code
复制代码

   四、一切事物皆对象

  类也是一种对象,是由type创建的。  

复制代码
# python中,一切事物皆对象。
class F00:
    def __iter__(self):
        pass
a = F00()
print(type(a))     # <class '__main__.F00'>
print(type(F00))   # <class 'type'>
# a是由FOO类创建的;F00类是由type类创建的。

# 引申创建类的另一种特殊方式:
def func (self):
    print('这是创建类的另一种方式')
F00 = type('F00',(),{'func':func})
# type()的单个参数分别是:类名(字符串)、基类()、函数(字典)
a = F00()
a.func()  # output:这是创建类的另一种方式
View Code
复制代码