python类特性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wenzhou1219/article/details/83242536

习惯了C++和Java OO(面向对象)思想的程序员刚转到python会有些不习惯,python中对很多操作都做了简化,完全的面向过程编程也很容易(事实上很多人确实在这样做),但是实际上python针对类提供了很多有用的特性,了解这些可以编写更好的Python OO程序。

1.命名元组

默认的python元组访问时,需要按照序号访问,这样一是不易阅读二是扩展比较困难,python collections组提供了命名元组的功能解决此功能,元组直接当做对象,元素当做对象属性即可。

import collections

# 命名元组
def name_tuple_test():
    User = collections.namedtuple('User', ['id', 'name', 'age', 'weight'])
    u = User(12, 'jim wen', 20, 140)
    print(u)
    print(u.id, u.name, u.age, u.weight)

2.函数对象

编程中我们经常抽象一个公用模型,通过指定回调函数来完成功能的定制和补充,c++中可以指定函数指针来完成,但是函数指针的可扩展性和复用性有限,最常见的是需要针对不同情况给回调一个初始值,这种情况更常用的做法是指定函数对象(重载()操作符);而在java中我们通常是指定一个接口来完成回调。引入lamda表达式后,c++和java都可以借助lamda表达式减少回调编程工作。

而在python中我们因为所有的类或函数都是一级对象,所以常常习惯是直接指定函数。在一些扩展性要求更强的情况,需要我们使用函数对象,如下:

class FillDefaultValue():
    def __init__(self, prefix):
        self.__data = prefix

    def __call__(self):
        return "other value-%d" %self.__data


def function_object_test():
    m = {"1": "one", "2": "two", "3": "three", "4": "four"}
    m_wrap = collections.defaultdict(FillDefaultValue(0), m)
    for i in xrange(1, 6):
        print("Index:%d , Result:%s\n" % (i, m_wrap[str(i)]))

这里通过重载__call__实现函数对象,这里借助函数对象我们可以在生成函数对象时指定默认值

3.操作符重写

OO编程中,重写操作符也是常用操作,特别在实现自定义数据结构时,为了和python内置操作保持同样范式,需要实现默认操作符重写。和java类似,python提供了指定操作类的基类接口,我们继承实现即可,这些接口在collections包中,如下我们实现一个最简单的List类,继承sequence基类:

class MyList(collections.Sequence):
    def __init__(self):
        self.__data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

    def __getitem__(self, i):
        return self.__data.__getitem__(i)

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


def my_list_test():
    l = MyList()
    for i in xrange(0, len(l)):
        print(l[i])

4.类泛型

简单点说:类制造对象,传入参数是数据;泛型制造类,传入参数是类。python中类型操作得到简化,通常我们只用到类->对象,但是有时会还是需要用到泛型。比如,需要定义一个函数来解析不同类型的Data,函数传入不同的类,需要制造出不同的类对象并用制造的对象解析数据。python中没有提供直接的泛型支持,但是通过classmethod属性可以完成类似操作,类成员函数第一个参数是self,即在类对象上操作,classmethod类函数第一个参数是类名,函数体中直接生产对应类对象,某种程度上简化了泛型的定义。

class GenericData():
    def output(self):
        pass

    @classmethod
    def create_class(cls, data):
        return cls(data)


class JsonData(GenericData):
    def __init__(self, data):
        self.__data = json.loads(data, "utf-8")

    def output(self):
        print(self.__data['key'])


class XmlData(GenericData):
    def __init__(self, data):
        self.__data = ET.fromstring(data)

    def output(self):
        print(self.__data.tag, self.__data.text)


def dump_data_test(d, data):
    d = d.create_class(data)
    d.output()

如下调用:

    dump_data_test(JsonData, '{"key":"Json Data"}')
    dump_data_test(XmlData, '<key>Xml Data</key>')

即完成泛型功能。

演示代码下载链接

原创,转载请注明来自http://blog.csdn.net/wenzhou1219

猜你喜欢

转载自blog.csdn.net/wenzhou1219/article/details/83242536