python学习之路-面向对象的编程
最近在自学python,突然想写点什么, 同时也是为了加深自己的记忆,想记录自己的点点滴滴,好了进入主题:
简介
这被称为面向过程的。还有一种把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。
这种方法称为 面向对象的 编程理念。在大多数时候你可以使用过程性编程,但是有些时候当你想要编写大型程
序或是寻求一个更加合适的解决方案的时候,你就得使用面向对象的编程技术。
类和对象是面向对象编程的两个主要方面。类创建一个新类型,而对象这个类的 实例 。这类似于你
有一个 int 类型的变量,这存储整数的变量是 int 类的实例(对象)。
注意,即便是整数也被作为对象(属于 int 类)。这和 c++、java(1.5 版之前)把整数纯粹作为类型是
不同的。通过 help(int)了解更多这个类的详情。 c#和 java 1.5 程序员会熟悉这个概念,因为它类似与封装
与解封装 的概念。
对象可以使用普通的 属于 对象的变量存储数据。属于一个对象或类的变量被称为域。对象也可以使
用属于 类的函数来具有功能。这样的函数被称为类的方法。这些术语帮助我们把它们与孤立的函数和变
量区分开来。域和方法可以合称为类的属性。
域有两种类型——属于每个实例/类的对象或属于类本身。它们分别被称为实例变量和类变量。
类使用 class 关键字创建。类的域和方法被列在一个缩进块中。
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用
这个方法的时候你不为这个参数赋值,python 会提供这个值。这个特别的变量指对象本身,按照惯例它的
名称是 self。
虽然你可以给这个参数任何名称,但是 强烈建议 你使用 self 这个名称——其他名称都是不赞成你使
用的。使用一个标准的名称有很多优点——你的程序读者可以迅速识别它,如果使用 self 的话,还有些 ide
(集成开发环境)也可以帮助你。
你一定很奇怪 python 如何给 self 赋值以及为何你不需要给它赋值。举一个例子会使此变得清晰。假如
你有一个类称为 myclass 和这个类的一个实例 myobject。当你调用这个对象的方法 myobject.method(arg1,
arg2)的时候,这会由 python 自动转为 myclass.method(myobject, arg1, arg2)——这就是 self 的原理了。
这也意味着如果你有一个不需要参数的方法,你还是得给这个方法定义一个 self 参数。
一个尽可能简单的类如下面这个例子所示。
创建一个类
[python] view plaincopy
#!/usr/bin/python
# filename: simplestclass.py
class person:
pass # an empty block
p = person()
print p
输出
[html] view plaincopy
horst@horst-k42jc:~/desktop/horstdemo/python$ python simplestclass.py
<__main__.person instance at 0xb77475cc>
我们使用 class 语句后跟类名,创建了一个新的类。这后面跟着一个缩进的语句块形成类体。在这个例
子中,我们使用了一个空白块,它由 pass 语句表示。
接下来,我们使用类名后跟一对圆括号来创建一个对象/实例。(我们将在下面的章节中学习更多的如
何创建实例的方法)。为了验证,我们简单地打印了这个变量的类型。它告诉我们我们已经在__main__模
块中有了一个 person 类的实例。
可以注意到存储对象的计算机内存地址也打印了出来。这个地址在你的计算机上会是另外一个值,因
为 python 可以在任何空位存储对象。
对象的方法
[python] view plaincopy
#!/usr/bin/python
# filename: method.py
class person:
def sayhi(self):
print 'hello, how are you?'
p = person()
p.sayhi()
输出
[python] view plaincopy
horst@horst-k42jc:~/desktop/horstdemo/python$ python method.py
hello, how are you?
__init__方法
在 python 的类中有很多方法的名字有特殊的重要意义。现在我们将学习__init__方法的意义。
__init__方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的 初
始化 。注意,这个名称的开始和结尾都是双下划线。
[python] view plaincopy
#!/usr/bin/python
# filename: class_init.py
class person:
def __init__(self, name):
self.name = name
def sayhi(self):
print 'hello, my name is', self.name
p = person('horst')
p.sayhi()
输出
[html] view plaincopy
horst@horst-k42jc:~/desktop/horstdemo/python$ python class_init.py
hello, my name is horst
这里,我们把__init__方法定义为取一个参数 name(以及普通的参数 self)。在这个__init__里,我们只
是创建一个新的域,也称为 name。注意它们是两个不同的变量,尽管它们有相同的名字。点号使我们能够
区分它们。
最重要的是,我们没有专门调用__init__方法,只是在创建一个类的新实例的时候,把参数包括在圆括
号内跟在类名后面,从而传递给__init__方法。这是这种方法的重要之处。
现在,我们能够在我们的方法中使用 self.name 域。这在 sayhi 方法中得到了验证。
类与对象的方法
我们已经讨论了类与对象的功能部分,现在我们来看一下它的数据部分。事实上,它们只是与类和对
象的名称空间 绑定 的普通变量,即这些名称只在这些类与对象的前提下有效。
有两种类型的 域 ——类的变量和对象的变量,它们根据是类还是对象 拥有 这个变量而区分。
类的变量 由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变
量做了改动的时候,这个改动会反映到所有其他的实例上。
对象的变量 由类的每个对象/实例拥有。因此每个对象有自己对这个域的一份拷贝,即它们不是共享
的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。通过一个例子会使这
个易于理解。
[python]
#!/usr/bin/python
# filename: objvar.py
class person:
'''''represents a person.'''
population = 0
def __init__(self, name):
'''''initializes the person's data.'''
self.name = name
print '(initializing %s)' % self.name
# when this person is created, he/she
# adds to the population
person.population += 1
def __del__(self):
'''''i am dying.'''
print '%s says bye.' % self.name
person.population -= 1
if person.population == 0:
print 'i am the last one.'
else:
print 'there are still %d people left.' % person.population
def sayhi(self):
'''''greeting by the person.
really, that's all it does.'''
print 'hi, my name is %s.' % self.name
def howmany(self):
'''''prints the current population.'''
if person.population == 1:
print 'i am the only person here.'
else:
print 'we have %d persons here.' % person.population
horst = person('horst')
horst.sayhi()
host.howmany()
kalam = person('abdul kalam')
kalam.sayhi()
kalam.howmany()
horst.sayhi()
horst.howmany()
输出:
[html]
horst@horst-k42jc:~/desktop/horstdemo/python$ python objvar.py
(initializing horst)
hi, my name is horst.
i am the only person here.
(initializing abdul kalam)
hi, my name is abdul kalam.
we have 2 persons here.
hi, my name is horst.
we have 2 persons here.
abdul kalam says bye.
there are still 1 people left.
horst says bye.
这个例子有助于说明类与对象的变量的本质。这里,population 属于 person 类,
因此是一个类的变量。name 变量属于对象(它使用 self 赋值)因此是对象的变量。
观察可以发现__init__方法用一个名字来初始化 person 实例。在这个方法中,我们让 population 增加 1,
这是因为我们增加了一个人。同样可以发现,self.name 的值根据每个对象指定,这表明了它作为对象的变
量的本质。
记住,你只能使用 self 变量来参考同一个对象的变量和方法。这被称为 属性参考 。
在这个程序中,我们还看到 docstring 对于类和方法同样有用。我们可以在运行时使用 person.__doc__
和 person.sayhi.__doc__来分别访问类与方法的文档字符串。
就如同__init__方法一样,还有一个特殊的方法__del__,它在对象消逝的时候被调用。对象消逝即对象
不再被使用,它所占用的内存将返回给作它用。在这个方法里面,我们只是简单地把 person.population
减 1。
当对象不再被使用时,__del__方法运行,但是很难保证这个方法究竟在 什么时候 运行。如果你想要
指明它的运行,你就得使用 del 语句,就如同我们在以前的例子中使用的那样。
哈哈, 今天就写到这里吧, 下一次再写继承吧, 希望能对了有所帮助。