【3.1.1】认识python的类

断断续续的写过几个类之后,对类有了一些基本的认知。突然认识到去年年初的时候,小龚看了我的代码,来了一句,我靠,你的class里面怎么都是staticmethod呀?

一、类的属性

要知道一个类有哪些属性,有两种方法。最简单的是使用 dir() 内建函数。另外是通过访问类的字典属性 dict

    >>> dir(MyClass)
    ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__form
    at__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__',
     '__lt__', '__module__', '__ne__', '__new__', '__qualname__', '__reduce__', '__r
    educe_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook
    __', '__weakref__', 'myVersion', 'showMyVersion']

    >>> MyClass.__dict__
    mappingproxy({'__module__': '__main__', '__qualname__': 'MyClass', '__weakref__'
    : <attribute '__weakref__' of 'MyClass' objects>, 'showMyVersion': , '__dict__': <attribute '__dict__' of 'MyClass ' objects>, 'myVersion': '1.1', '__doc__': 'MyClass class definition'})
    dir() 返回的仅是对象的属性的一个名字类表,而 __dict__

返回的是一个字典,它的键(key)是属性名,键值(value)是相应的属性对象的数据值。

特殊的类属性

C.__name__  类C的名字(字符串)
C.__doc__           类C的文档字符串
C.__bases__         类C的所有父类构成的元组
C.__dict__          类C的属性
C.__module__            类C定义所在的模块
C.__class__         实例C对应的类
__name__ 是给定类的字符名字。它适用于那种只需要字符串(类对象的名字),而非对象本身的情况。
__doc__是类的文档字符串,与函数及模块的文档字符串相似,必须紧随头行后的字符串。文档字符串不

能被派生类继承,也就是说派生类必须含有他们自己的文档字符串。__bases__用来处理继承,它包含了一个由所有父类组成的元组。__dict__属性包含一个字典,由类的数据属性组成。

    >>> MyClass.__name__
    'MyClass'
    >>> MyClass.__doc__
    'MyClass class definition'
    >>> MyClass.__bases__
    (<class 'object'>,)
    >>> print(MyClass.__dict__)
    {'__module__': '__main__', '__qualname__': 'MyClass', '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 'showMyVersion': , '__dict__': <attribute '__dict__' of 'MyClass' objects>, '
    myVersion': '1.1', '__doc__': 'MyClass class definition'}

一、classmethod和staticmethod区别

类和实例都是对象.

所以它们可以有方法.

类的方法就叫类方法.

实例的方法就叫实例方法.

至于静态方法就是写在类里的方法,必须用类来调用(极少数情况下使用,一般都在全局里直接写函数了)

class Kls(object):
    def __init__(self, data):
        self.data = data
    def printd(self):
        print(self.data)
    @staticmethod
    def smethod(*arg):
        print('Static:', arg)
    @classmethod
    def cmethod(*arg):
        print('Class:', arg)

    >>> ik = Kls(23)
    >>> ik.printd()
    23
    >>> ik.smethod()
    Static: ()
    >>> ik.cmethod()
    Class: (<class '__main__.Kls'>,)
    >>> Kls.printd()
    TypeError: unbound method printd() must be called with Kls instance as first argument (got nothing instead)
    >>> Kls.smethod()
    Static: ()
    >>> Kls.cmethod()
    Class: (<class '__main__.Kls'>,)
    class Data_test2(object):
        day=0
        month=0
        year=0
        def __init__(self,year=0,month=0,day=0):
            self.day=day
            self.month=month
            self.year=year

        @classmethod
        def get_date(cls,data_as_string):
            #这里第一个参数是cls, 表示调用当前的类名
            year,month,day=map(int,string_date.split('-'))
            date1=cls(year,month,day)
            #返回的是一个初始化后的类
            return date1

        def out_date(self):
            print "year :"
            print self.year
            print "month :"
            print self.month
            print "day :"
            print self.day

在Date_test类里面创建一个成员函数, 前面用了@classmethod装饰。 它的作用就是有点像静态类,比静态类不一样的就是它可以传进来一个当前类作为第一个参数。

r=Data_test2.get_date("2016-8-6")
r.out_date()
输出:

year :
2016
month :
8
day :
1

案例

import os
os.chdir('E:\\py\\chapter6')

def sanitize(time_string):
    if '-' in time_string:
        splitter='-'
    elif ':' in time_string:
        splitter=':'
    else:
        return(time_string)
    (mins,secs)=time_string.split(splitter)
    return(mins +'.' + secs)

class Athlete:
    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.name=a_name
        self.dob=a_dob
        self.times=a_times
    def top3(self):
        return(sorted(set([sanitize(t) for t in self.times]))[0:3])
    def add_time(self,time_value):
        self.times.append(time_value)
    def add_times(slef,list_of_times):
        self.times.extend(list_of_times)


def get_coach_data(filename):
    try:
        with open(filename) as f:
            data=f.readline()
            templ=data.strip().split(',')
            return(Athlete(templ.pop(0),templ.pop(0),templ))
    except IOError as ioerr:
        print('File error:' +str(ioerr))
        return(None)


sarah=get_coach_data('sarah2.txt')
print(sarah.name+"'s fastest times are:"+str(sarah.top3()))

也可调用内置的类,建立类的父子关系

import os
os.chdir('E:\\py\\chapter6')

def sanitize(time_string):
    if '-' in time_string:
        splitter='-'
    elif ':' in time_string:
        splitter=':'
    else:
        return(time_string)
    (mins,secs)=time_string.split(splitter)
    return(mins +'.' + secs)

class Athlete(list):
    def __init__(self,a_name,a_dob=None,a_times=[]):
        list.__init__([])
        self.name=a_name
        self.dob=a_dob
        self.extend(a_times)
    def top3(self):
        return(sorted(set([sanitize(t) for t in self]))[0:3])


def get_coach_data(filename):
    try:
        with open(filename) as f:
            data=f.readline()
            templ=data.strip().split(',')
            return(Athlete(templ.pop(0),templ.pop(0),templ))
    except IOError as ioerr:
        print('File error:' +str(ioerr))
        return(None)


sarah=get_coach_data('sarah2.txt')
print(sarah.name+"'s fastest times are:"+str(sarah.top3()))

参考资料

个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn

Sam avatar
About Sam
专注生物信息 专注转化医学