不一样的Python(8)——类型

1. 以关键字class开始定义一个新的类型:
class Employee:
  def setname(self, who):
    self.name = who
  def display(self):
    print self.name 

self相当于C++中的this指针。C++的this指针是隐含的,但Python中self是需要显示地写出。

2. Python 把对象(object)分为class object和instance object。每个类型都有一个对象,该对象能生成多个实例对象。

3. 可以通过类型对象或者实例对象调用类型的方法。比如下列两种调用setname的方式是等价的:

e = Employee()
e.setname('Harry')
Employee.setname(e, 'Harry')

4. 实例对象的成员变量不需要提前声明,它们在赋值时自动创建。

5. 可以在类型定义之外为实例对象添加新的成员变量,比如:

e.lastname = 'He'

6. 可以在类型定义之外为类型添加新的成员函数,比如:

def upperName(self):
  return self.name.upper()

Employee.method = upperName
e.method()

7. 如果子类没有重写__init__,会自动调用父类的__init__函数:

class A:
    def __init__(self):
        print 'A is instantiated'


class B (A):
    pass

if __name__ == '__main__':
    b = B()

此时A.__init__仍然会被调用

如果子类重写了__init__函数,父类的__init__函数不会自动自动被调用,如以下代码:

class A:
    def __init__(self):
        print 'A is instantiated'


class B (A):
    def __init__(self):
        print 'B is instantiated'
    

if __name__ == '__main__':
    b = B()


如果希望父类的__init__函数被调用,需要在子类的__init__函数里显示地调用:如以下代码:

class A:
    def __init__(self):
        print 'A is instantiated'


class B (A):
    def __init__(self):
        A.__init__(self)
        print 'B is instantiated'
    

if __name__ == '__main__':
    b = B()


8. Python的class不支持类似于C++/C#/Java的static函数/方法

9. metaclass可以用来生成新的class。详细讨论可以参考http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

10. static变量和实例的变量:

>>> class Test(object):
...     i = 3
...
>>> Test.i
3
>>> t = Test()
>>> t.i     # static variable accessed via instance
3
>>> t.i = 5 # but if we assign to the instance ...
>>> Test.i  # we have not changed the static variable
3
>>> t.i     # we have overwritten Test.i on t by creating a new attribute t.i
5
>>> Test.i = 6 # to change the static variable we do it by assigning to the class
>>> t.i
5
>>> Test.i
6

11.在Python中没有类似于C/C++/C#的enum类型。下面是几种用Python模拟enum的方法:

(1) 生成新的type:

def enum(**enums):
    return type('Enum', (), enums)

>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'

或者自动编号:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)

>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1

如果需要逆向查找:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    reverse = dict((value, key) for key, value in enums.iteritems())
    enums['reverse_mapping'] = reverse
    return type('Enum', (), enums)

>>> Numbers.reverse_mapping['three']
'THREE'

(2)基于set:

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError
Animals = Enum(["DOG", "CAT", "HORSE"])

print Animals.DOG

(3)基于tuple:

(Pen, Pencil, Eraser) = range(0, 3)

或者:

class Stationery:
    (Pen, Pencil, Eraser) = range(0, 3)

12. 如果类型需要支持+、-、×、/,则需要添加__add__、__sub__、__mul__、__rmul__、__div__等。如果需要支持比较,则需要添加__cmp__。完整列表参考Think like a Computer Scientist的Appendix B。








 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值