类的定义

Python中使用class这个关键词来定义类:


#
# This is an empty class.
#
class AClass:
    pass

这里定义了一个空的类,不过这里有一个问题,如果一个类没有定义__init__函数,会报告警,所以之类还是加上:


#
# This is an empty class.
#
class AClass:
    def __init__(self):
        pass

这样就是一个比较完整的类了。

这里__init__就是一个构造器。

对于上述这样的空类,其实作用不大,仅仅用作命名空间(namespace),可以存放变量之类的:


#
# This is an empty class.
#
class AClass:
    def __init__(self):
        pass

def Sum(x, y):
    print "%d" % (x + y)

if __name__ == "__main__":
    a = AClass()
    a.x = 0
    a.y = 1
    a.func = Sum
    a.func(a.x, a.y)

上面用到了类的实例化,即a = AClass()。

类的成员

类中可以有静态的数据:


#
# This is a class.
#
class AClass:
    Version = 1.0       # Static data.
    def __init__(self):
        pass

if __name__ == "__main__":
    a = AClass()
    print a.Version
    print AClass.Version

类中还可以有函数,一般不叫函数叫方法:

#
# This is a class.
#
class AClass:
    Version = 1.0       # Static data.
    
    def __init__(self):
        pass
    
    def printVersion(self):
        print self.Version

if __name__ == "__main__":
    a = AClass()
    a.printVersion()

可以看到__init__其实也算是方法,两者的定义方式一致。

类中的方法需要跟类的实例绑定,它一般有一个参数self,表示实例本身;

调用方法的时候不需要特别指定这个参数。

类中有很多特定的属性:


if __name__ == "__main__":
    print dir(AClass)

使用dir来查看属性,下面是结果:

['Version', '__doc__', '__init__', '__module__', 'printVersion']

打印结果如下:


['Version', '__doc__', '__init__', '__module__', 'printVersion']
1.0
None
<unbound method AClass.__init__>
__main__
<unbound method AClass.printVersion>

这里需要注意:

1. __doc__的值是None,是因为没有定义类的说明,可以通过在class定义之后的下一行加入字符串说明:

#
# This is a class.
#
class AClass:
    'This is a class'
    Version = 1.0       # Static data.
    
    def __init__(self):
        pass
    
    def printVersion(self):
        print self.Version

2. 后面的unbound的原因是因为没有绑定实例,修改后:

if __name__ == "__main__":
    a = AClass()
    print dir(AClass)
    print a.Version
    print a.__doc__
    print a.__init__
    print a.__module__
    print a.printVersion

其结果如下:

['Version', '__doc__', '__init__', '__module__', 'printVersion']
1.0
This is a class
<bound method AClass.__init__ of <__main__.AClass instance at 0x00000000056B4D48>>
__main__
<bound method AClass.printVersion of <__main__.AClass instance at 0x00000000056B4D48>>

前面提到方法与实例是绑定的,也存在两种方法虽然定义在类中,但是不需要与类绑定,它们是静态方法和类方法:

#
# This is a class.
#
class AClass:
    'This is a class'
    Version = 1.0       # Static data.
    
    def __init__(self):
        pass
    
    def printVersion(self):
        print self.Version
    
    @staticmethod
    def printVersionSts():
        print "%d" % AClass.Version
    
    @classmethod
    def printVersionCls(cls):
        print "%d" % cls.Version

if __name__ == "__main__":
    print AClass.printVersionSts
    print AClass.printVersionCls
    AClass.printVersionSts()
    AClass.printVersionCls()

得到的结果如下:

<function printVersionSts at 0x0000000004D52128>
<bound method classobj.printVersionCls of <class __main__.AClass at 0x00000000047F9828>>
1
1

静态方法和类方法通过@staticmethod和@classmethod来修饰。

可以看到它们是直接的绑定的。

类成员一般会区分Public,Private等的,默认Python只有Public类,但是可以通过一些方法类指定Private的类。

在成员名前加双下划线来实现:

#
# This is a class.
#
class AClass:
    'This is a class'
    Version = 1.0       # Static data.
    
    def __init__(self):
        pass
    
    def __printVersion(self):
        print self.Version

if __name__ == "__main__":
    a = AClass()
    a.__printVersion()

这个时候PyLint会报错:

PyLint: Access to a protected member __printVersion of a client class

执行的时候会报错:

Traceback (most recent call last):
  File "D:\Code\python_tool_code\LearningPython\Class.py", line 20, in <module>
    a.__printVersion()
AttributeError: AClass instance has no attribute '__printVersion'

类的继承

Python中继承直接使用圆括号()



#
# Define a father class.
#
class Father:
    #
    # __init__ should be defined.
    #
    def __init__(self, name):
        self.name = name
    
    def introduceYourself(self):
        print "This is %s." % self.name
#
# Inheritance from Father.
#
class Children(Father):          # Use "()" for interitance.
    pass

这里就定义了一个继承类Children。

下面是一些使用代码:


#
# Inheritance from Father.
#
class Children(Father):          # Use "()" for interitance.
    def introduceYourself(self):
        Father.introduceYourself(self)
        print "This is drived from Father."

if __name__ == "__main__":
    p = Father("father")
    print Father.__bases__
    p.introduceYourself()
     
    s = Children("son")
    print Children.__bases__
    s.introduceYourself()

下面是运行的结果:


()
This is father.
(<class __main__.Father at 0x0000000004D38BE8>,)
This is son.
This is drived from Father.

需要说明的是:

1. 这里Father没有指定从哪里继承,实际默认就是从object继承;不过手动指定之后:


class Father(object):

得到的结果如下:

(<type 'object'>,)

2. Children从Father继承了所以可以看到__bases__有打印;

3. 子类可以Override父类的方法;

4. 子类会自动调用父类的__init__方法,除非子类Override了父类的__init__方法,此时就需要在子类的__init__里面指定调用父类的__init__(除非不需要);

Python支持多重继承,这里先不讲。