类和实例

这里以动物(Animal)类为例,Python 提供关键字 来声明一个类:

其中,Animal 是类名,通常类名的首字母采用大写(如果有多个单词,则每个单词的首字母大写),后面紧跟着 (object),表示该类是从哪个类继承而来的,所有类最终都会继承自 object 类。

类定义好了,接下来我们就可以创建实例了:

  1. >>> animal = Animal() # 创建一个实例对象
  2. >>> animal
  3. <__main__.Animal at 0x1030a44d0>

我们在创建实例的时候,还可以传入一些参数,以初始化对象的属性,为此,我们需要添加一个 __init__ 方法:

  1. class Animal(object):
  2. def __init__(self, name):
  3. self.name = name

然后,在创建实例的时候,传入参数:

  1. >>> animal = Aniaml('dog1') # 传入参数 'dog1'
  2. >>> animal.name # 访问对象的 name 属性
  3. 'dog1'

我们可以把 __init__ 理解为对象的初始化方法,它的第一个参数永远是 self,指向创建的实例本身。定义了 __init__ 方法,我们在创建实例的时候,就需要传入与 __init__ 方法匹配的参数。

我们添加了方法 greet,看看下面的使用:

  1. >>> dog1 = Animal('dog1')
  2. >>> dog1.name
  3. 'dog1'
  4. >>> dog1.greet()
  5. Hello, I am dog1.

现在,让我们做一下总结。我们在 Animal 类定义了两个方法:__init__greet__init__ 是 Python 中的特殊方法(special method),它用于对对象进行初始化,类似于 C++ 中的构造函数;greet 是我们自定义的方法。

注意到,我们在上面定义的两个方法有一个共同点,就是它们的第一个参数都是 self,指向实例本身,也就是说它们是和实例绑定的函数,这也是我们称它们为方法而不是函数的原因。

访问限制

在某些情况下,我们希望限制用户访问对象的属性或方法,也就是希望它是私有的,对外隐蔽。比如,对于上面的例子,我们希望 name 属性在外部不能被访问,我们可以在属性或方法的名称前面加上两个下划线,即 __,对上面的例子做一点改动:

  1. class Animal(object):
  2. def __init__(self, name):
  3. def greet(self):
  4. print 'Hello, I am %s.' % self.__name
  1. >>> dog1 = Animal('dog1')
  2. >>> dog1.__name # 访问不了
  3. ---------------------------------------------------------------------------
  4. <ipython-input-206-7f6730db631e> in <module>()
  5. ----> 1 dog1.__name
  6. AttributeError: 'Animal' object has no attribute '__name'
  7. >>> dog1.greet() # 可以访问
  8. Hello, I am dog1.

可以看到,加了 ____name 是不能访问的,而原来的 greet 仍可以正常访问。

需要注意的是,在 Python 中,以双下划线开头,并且以双下划线结尾(即 __xxx__)的变量是特殊变量,特殊变量是可以直接访问的。所以,不要用 __name__ 这样的变量名。

获取对象信息

当我们拿到一个对象时,我们往往会考察它的类型和方法等,比如:

当我们拿到一个类的对象时,我们用什么去考察它呢?回到前面的例子:

  1. class Animal(object):
  2. def __init__(self, name):
  3. self.name = name
  4. def greet(self):
  5. print 'Hello, I am %s.' % self.name
  • 第 1 招:使用 type

使用 type(obj) 来获取对象的相应类型:

  1. >>> dog1 = Animal('dog1')
  2. >>> type(dog1)
  3. __main__.Animal
  • 第 2 招:使用 isinstance

使用 isinstance(obj, type) 判断对象是否为指定的 type 类型的实例:

  1. >>> isinstance(dog1, Animal)
  2. True
  • 第 3 招:使用

    • 使用 hasattr(obj, attr) 判断对象是否具有指定属性/方法;
    • 使用 getattr(obj, attr[, default]) 获取属性/方法的值, 要是没有对应的属性则返回 default 值(前提是设置了 default),否则会抛出 AttributeError 异常;
    • 使用 setattr(obj, attr, value) 设定该属性/方法的值,类似于 obj.attr=value;

看下面例子:

  • 第 4 招:使用 dir
  1. >>> dir(dog1)
  2. ['__class__',
  3. '__delattr__',
  4. '__doc__',
  5. '__format__',
  6. '__getattribute__',
  7. '__hash__',
  8. '__init__',
  9. '__module__',
  10. '__new__',
  11. '__reduce__',
  12. '__reduce_ex__',
  13. '__repr__',
  14. '__setattr__',
  15. '__sizeof__',
  16. '__str__',
  17. '__subclasshook__',
  18. '__weakref__',
  19. 'age',
  20. 'greet',
  21. 'name']

小结

  • 类是具有相同属性方法的一组对象的集合,实例是一个个具体的对象。
  • 方法是与实例绑定的函数。
  • 获取对象信息可使用下面方法:
    • type(obj):来获取对象的相应类型;
    • isinstance(obj, type):判断对象是否为指定的 type 类型的实例;
    • hasattr(obj, attr):判断对象是否具有指定属性/方法;
    • getattr(obj, attr[, default]) 获取属性/方法的值, 要是没有对应的属性则返回 default 值(前提是设置了 default),否则会抛出 AttributeError 异常;
    • setattr(obj, attr, value):设定该属性/方法的值,类似于 obj.attr=value;

参考资料