Python 面向对象的基本概念 与c++ 面向对象的基本概念有点区别
来源:互联网 发布:qq飞车绿光使者数据 编辑:程序博客网 时间:2024/06/14 07:22
Python使用类(class)和对象(object),进行面向对象(object-oriented programming,简称OOP)的编程。面向对象的最主要目的是提高程序的重复使用性。我们这么早切入面向对象编程的原因是,Python的整个概念是基于对象的。了解OOP是进一步学习Python的关键。
下面是对面向对象的一种理解,基于分类。
相近对象,归为类
在人类认知中,会根据属性相近把东西归类,并且给类别命名。比如说,鸟类的共同属性是有羽毛,通过产卵生育后代。任何一只特别的鸟都在鸟类的原型基础上的。
面向对象就是模拟了以上人类认知过程。在Python语言,为了听起来酷,我们把上面说的“东西”称为对象(object)。
先定义鸟类class Bird(object): have_feather = True way_of_reproduction = 'egg'
我们定义了一个类别(class),就是鸟(Bird)。在隶属于这个类比的语句块中,我们定义了两个变量,一个是有羽毛(have_feather),一个是生殖方式(way_of_reproduction),这两个变量对应我们刚才说的属性(attribute)。我们暂时先不说明括号以及其中的内容,记为问题1。
注:在Python中,属性值都是在声明的时候就赋值了。C++,是对象自己去赋值。
假设我养了一只小鸡,叫summer。它是个对象,且属于鸟类。使用前面定义的类:
summer = Bird()print summer.way_of_reproduction通过第一句创建对象,并说明summer是类别鸟中的一个对象,summer就有了鸟的类属性,对属性的引用是通过对象.属性(object.attribute) 的形式实现的。
动作
日常认知中,我们在通过属性识别类别的时候,有时根据这个东西能做什么事情来区分类别。比如说,鸟会移动。这样,鸟就和房屋的类别区分开了。这些动作会带来一定的结果,比如移动导致位置的变化。
这样的一些“行为”属性为方法(method)。Python中通过在类的内部定义函数,来说明方法
class Bird(object): have_feather = True way_of_reproduction = 'egg' def move(self, dx, dy): position = [0,0] position[0] = position[0] + dx position[1] = position[1] + dy return positionsummer = Bird()print 'after move:',summer.move(5,8)子类
类别本身还可以进一步细分成子类
比如说,鸟类可以进一步分成鸡,大雁,黄鹂。
在OOP中,我们通过继承(inheritance)来表达上述概念。
class Chicken(Bird): way_of_move = 'walk' possible_in_KFC = Trueclass Oriole(Bird): way_of_move = 'fly' possible_in_KFC = Falsesummer = Chicken()print summer.have_featherprint summer.move(5,8)
新定义的鸡(Chicken)类的,增加了两个属性:移动方式(way_of_move),可能在KFC找到(possible_in_KFC)
在类定义时,括号里为了Bird。这说明,Chicken是属于鸟类(Bird)的一个子类,即Chicken继承自Bird。自然而然,Bird就是Chicken的父类。Chicken将享有Bird的所有属性。尽管我只声明了summer是鸡类,它通过继承享有了父类的属性(无论是变量属性have_feather还是方法属性move)
新定义的黄鹂(Oriole)类,同样继承自鸟类。在创建一个黄鹂对象时,该对象自动拥有鸟类的属性。
通过继承制度,我们可以减少程序中的重复信息和重复语句。如果我们分别定义两个类,而不继承自鸟类,就必须把鸟类的属性分别输入到鸡类和黄鹂类的定义中。整个过程会变得繁琐,因此,面向对象提高了程序的可重复使用性。
(回到问题1, 括号中的object,当括号中为object时,说明这个类没有父类(到头了))
//----------------------------------------------------------------------------------
下面要阐述的是Python面向对象的独特之处
调用类的其他信息
上一讲中提到,在定义方法时,必须有self这一参数。这个参数表示某个对象。对象拥有类的所有性质,那么我们可以通过self,调用类属性。
class Human(object): laugh = 'hahahaha' def show_laugh(self): print self.laugh def laugh_100th(self): for i in range(100): self.show_laugh()li_lei = Human() li_lei.laugh_100th()self 是不是可以类比为C++的*this指针
这里有一个类属性laugh。在方法show_laugh()中,通过self.laugh,调用了该属性的值。
还可以用相同的方式调用其它方法。方法show_laugh(),在方法laugh_100th中()被调用。
通过对象可以修改类属性值。但这是危险的。类属性被所有同一类及其子类的对象共享。类属性值的改变会影响所有的对象。
现在要强调两个不同的概念类属性和对象属性
类属性:就是所有对象共有的,改变了类属性,则所有对象的对应属性值都会被改变,也就是所有变量共享一个类属性,相当于C++的static成员变量。
对象属性:每个对象独有的,改变对象属性,不会影响到其他对象的值,相当于C++中的成员变量。
举个例子:
class Human(object): Can_Talk = True Can_Walk = True Age = 0 Name = ["Li", "Lei"] a = Human()b = Human() a.Age += 1print a.Ageprint b.Age a.Name[0] = "Wang"print a.Nameprint b.Name输出的结果:
>>>
1
0
['Wang', 'Lei']
['Wang', 'Lei']
>>>
如果类属性的类型是immutable,在更改对象属性时,该属性会被复制出一个副本,存放在对象的__dict__中。你可以通过下面的方式查看:
print a.__class__.__dict__
print a.__dict__
注意到类中和对象中各有一个Age。一个为0, 一个为1。所以我们在查找a.Age的时候,会先查到对象的_ _dict__的值,也就是1。
但mutable的类属性,在更改属性值时,并不会有新的副本。所以更改会被所有的对象看到。
所以,为了避免混淆,最好总是区分类属性和对象的属性,而不能依赖上述的immutable属性的复制机制。
//那如何来设置Python对象的对象属性呢?
_init()_()方法
__init__()是一个特殊方法(special method)。Python有一些特殊方法。Python会特殊的对待它们。特殊方法的特点是名字前后有两个下划线。
如果你在类中定义了__init__()这个方法,创建对象时,Python会自动调用这个方法。这个过程也叫初始化。
相当于C++中的默认构造函数class happyBird(Bird): def __init__(self,more_words): print 'We are happy birds.',more_wordssummer = happyBird('Happy,Happy!')
尽管我们只是创建了summer对象,但__init__()方法被自动调用了。最后一行的语句(summer = happyBird...)先创建了对象,然后执行:
summer.__init__(more_words)
'Happy,Happy!' 被传递给了__init__()的参数more_words
对象的性质我们讲到了许多属性,但这些属性是类的属性。所有属于该类的对象会共享这些属性。比如说,鸟都有羽毛,鸡都不会飞。类属性。属于该类的所有对象该属性值都是相同的。
在一些情况下,我们定义对象的性质,用于记录该对象的特别信息。比如说,人这个类。性别是某个人的一个性质,不是所有的人类都是男,或者都是女。这个性质的值随着对象的不同而不同。李雷是人类的一个对象,性别是男;韩美美也是人类的一个对象,性别是女。
当定义类的方法时,必须要传递一个self的参数。这个参数指代的就是类的一个对象。我们可以通过操纵self,来修改某个对象的性质。比如用类来新建一个对象,即下面例子中的li_lei, 那么li_lei就被self表示。我们通过赋值给self.attribute,给li_lei这一对象增加一些性质,比如说性别的男女。self会传递给各个方法。在方法内部,可以通过引用self.attribute,查询或修改对象的性质。
这样,在类属性的之外,又给每个对象增添了各自特色的性质,从而能描述多样的世界。
class Human(object): def __init__(self, input_gender): self.gender = input_gender def printGender(self): print self.genderli_lei = Human('male') # 这里,'male'作为参数传递给__init__()方法的input_gender变量。print li_lei.genderli_lei.printGender()
在初始化中,将参数input_gender,赋值给对象的性质,即self.gender。
li_lei拥有了对象性质gender。gender不是一个类属性。Python在建立了li_lei这一对象之后,使用li_lei.gender这一对象性质,专门储存属于对象li_lei的特有信息。
对象的性质也可以被其它方法调用,调用方法与类属性的调用相似,正如在printGender()方法中的调用。
- Python 面向对象的基本概念 与c++ 面向对象的基本概念有点区别
- python-面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- 面向对象的基本概念
- STL-queue
- Mybatis传多个参数(三种解决方案)
- 接单流程
- MappedByteBuffer
- EXCEL表的MFC导入
- Python 面向对象的基本概念 与c++ 面向对象的基本概念有点区别
- base64
- 二分匹配_HDU_1525
- java数组操作类:Arrays
- shell脚本
- STL-functional
- 使用系统控件UISearchBar实现APP中搜索功能
- text文本输入表单input和textarea
- STL-allocator