最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
python面向对象的学习笔记
时间:2015-03-24 编辑:简简单单 来源:一聚教程网
创建类:
#!/usr/bin/python
# Filename: simplestclass.py
class Person:
pass # An empty block
p = Person()
print p
$ python simplestclass.py
<__main__.Person instance at 0xf6fcb18c>
我们使用类名后跟一对圆括号来创建一个对象/实例。为了验证,我们简单地打印了这个变量的类型。它告诉我们我们已经在__main__模块中有了一个Person类的实例。
可以注意到存储对象的计算机内存地址也打印了出来。这个地址在你的计算机上会是另外一个值,因为Python可以在任何空位存储对象。
对象中的方法
我们已经讨论了类/对象可以拥有像函数一样的方法,这些方法与函数的区别只是一个额外的self变量。现在我们来
学习一个例子。
#!/usr/bin/python
# Filename: method.py
class Person:
def sayHi(self):
print 'Hello, how are you?'
p = Person()
p.sayHi()
$ python method.py
Hello, how are you?
这里我们看到了self的用法。注意sayHi方法没有任何参数,但仍然在函数定义时有self。
__init__方法:
__init__方法在类的一个对象被建立时,马上运行。这个方法可以用来对你的对象做一些你希望的 初始化 。
#!/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('Swaroop')
p.sayHi()
$ python class_init.py
Hello, my name is Swaroop
类与对象的方法
我们已经讨论了类与对象的功能部分,现在我们来看一下它的数据部分。事实上,它们只是与类和对象的名称空间 绑定 的普通变量,即这些名称只在这些类与对象的前提下有效。
有两种类型的 域 ——类的变量和对象的变量,它们根据是类还是对象 拥有 这个变量而区分。
类的变量 由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。
对象的变量 由类的每个对象/实例拥有。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。通过一个例子会使这个易于理解。
使用类与对象的变量
#!/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
swaroop = Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()
kalam = Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()
swaroop.sayHi()
swaroop.howMany()
$ python objvar.py
(Initializing Swaroop)
Hi, my name is Swaroop.
I am the only person here.
(Initializing Abdul Kalam)
Hi, my name is Abdul Kalam.
We have 2 persons here.
Hi, my name is Swaroop.
We have 2 persons here.
Abdul Kalam says bye.
There are still 1 people left.
Swaroop says bye.
I am the last one.
使用继承:
#!/usr/bin/python
# Filename: inherit.py
class SchoolMember:
'''Represents any school member.'''
def __init__(self, name, age):
self.name = name
self.age = age
print '(Initialized SchoolMember: %s)' % self.name
def tell(self):
'''Tell my details.'''
print 'Name:"%s" Age:"%s"' % (self.name, self.age),
class Teacher(SchoolMember):
'''Represents a teacher.'''
def __init__(self, name, age, salary):
SchoolMember.__init__(self, name, age)
self.salary = salary
print '(Initialized Teacher: %s)' % self.name
def tell(self):
SchoolMember.tell(self)
print 'Salary: "%d"' % self.salary
class Student(SchoolMember):
'''Represents a student.'''
def __init__(self, name, age, marks):
SchoolMember.__init__(self, name, age)
self.marks = marks
print '(Initialized Student: %s)' % self.name
def tell(self):
SchoolMember.tell(self)
print 'Marks: "%d"' % self.marks
t = Teacher('Mrs. Shrividya', 40, 30000)
s = Student('Swaroop', 22, 75)
print # prints a blank line
members = [t, s]
for member in members:
member.tell() # works for both Teachers and Students
$ python inherit.py
(Initialized SchoolMember: Mrs. Shrividya)
(Initialized Teacher: Mrs. Shrividya)
(Initialized SchoolMember: Swaroop)
(Initialized Student: Swaroop)
Name:"Mrs. Shrividya" Age:"40" Salary: "30000"
Name:"Swaroop" Age:"22" Marks: "75"
Python不会自动调用基本类的constructor
Python面向对象特征总结
一、封装
面向对象程序设计中的术语对象(Object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。传统意义上的“程序=数据结构+算法”被封装”掩盖“并简化为“程序=对象+消息”。对象是类的实例,类的抽象则需要经过封装。封装可以让调用者不用关心对象是如何构建的而直接进行使用。
一个简单的Python类封装如下:
Encapsulation
上面简单的示例代码可以看出,Python中的类包含了一般面向对象编程语言的主要元素,比如构造方法、绑定方法、静态方法、属性等,如果深入下去,还可以发现Python中内置了很多面向对象的“高级”主题,比如迭代器、反射、特性等等,提供了封装的直接构造要素。
二、继承
1、类继承
继承给人的直接感觉是这是一种复用代码的行为。继承可以理解为它是以普通的类为基础建立专门的类对象,子类和它继承的父类是IS-A的关系。一个简单而不失经典的示例如下:
Inheritance
一个显而易见的特点是,Python的面向对象的继承特征是基于类(class)的,比javascript基于原型(prototype)的继承更容易组织和编写代码,也更容易让人接受和理解。
ps:最近几天Anders大神搞出来的TypeScript横空出世,看它的语言规范里继承也是基于类的:
TypeScript-SimpleInheritance
感觉基于类的继承的语言好像在实现OO的可读性和编程体验上都不太差,据传说javascript是码农最想喷也是喷过最多f**k的语言。
2、多重继承
不同于C#,Python是支持多重类继承的(C#可继承自多个Interface,但最多继承自一个类)。多重继承机制有时很好用,但是它容易让事情变得复杂。一个多重继承的示例如下:
MultInheritance
如你所看到的那样,多重继承的好处显而易见,我们可以轻而易举地通过类似“组合”的方式复用代码构造一个类型。
有个需要注意的地方,即如果一个方法从多个超类继承,那么务必要小心继承的超类(或者基类)的顺序:
MultInheritance
我们为动物和机器各实现一个相同名称的move方法,但是输出因为继承的顺序而有所不同,Python在查找给定方法或者特性时访问超类的顺序被称为MRO(Method Resolution Order,方法判定顺序)。
三、多态
多态意味着可以对不同的对象使用同样的操作,但它们可能会以多种形态呈现出结果。在Python中,任何不知道对象到底是什么类型,但又需要对象做点什么的时候,都会用到多态。
能够直接说明多态的两段示例代码如下:
1、方法多态
Method-Polymorphism
对于一个临时对象obj,它通过Python的随机函数取出来,不知道具体类型(是字符串、元组还是自定义类型),都可以调用count方法进行计算,至于count由谁(哪种类型)去做怎么去实现我们并不关心。
有一种称为”鸭子类型(duck typing)“的东西,讲的也是多态:
DuckTyping
就in_the_forest函数而言,参数对象是一个鸭子类型,它实现了方法多态。但是实际上我们知道,从严格的抽象来讲,Person类型和Duck完全风马牛不相及。
2、运算符也多态
Operator-Polymorphism
上例中,显而易见,Python的加法运算符是”多态“的,理论上,我们实现的add方法支持任意支持加法的对象,但是我们不用关心两个参数x和y具体是什么类型。
一两个示例代码当然不能从根本上说明多态。普遍认为面向对象最有价值最被低估的特征其实是多态。我们所理解的多态的实现和子类的虚函数地址绑定有关系,多态的效果其实和函数地址运行时动态绑定有关。在C#中实现多态的方式通常有重写和重载两种,从上面两段代码,我们其实可以分析得出Python中实现多态也可以变相理解为重写和重载。在Python中很多内置函数和运算符都是多态的。
号外:在C#中,我们熟知接口(Interface)和多态相关,在处理多态对象时,只要关心它的接口(或者称为“协议”)而不需要显式指定特定实现类型即可,这也是IoC中面向接口(抽象)而不依赖于具体实现编程的基础。可惜在Python中根本没有Interface(有抽象类)。而在TypeScript的Specification中引入了Interface的概念:
TypeScript-Interface
TypeScript语言规范里对Interface的定义是命名的对象类型(Programmers can give names to object types; we call named object types interfaces. )。它直接等价于下面的Ojbect Type:
var Friend: () => {
name: string; favoriteColor?: string;
};
上面这个Object Type在Playgound中等价的javascript代码如下:
var Friend;
在TypeScript编程规范文档里,对Interface的一些说明:
Interfaces provide the ability to give names to object types and the ability to compose existing named object types into new ones.
Interfaces have no run-time representation—they are purely a compile-time construct. Interfaces are particularly useful for documenting and validating the required shape of properties, objects passed as parameters, and objects returned from functions.
Interface可以继承自Interface:
TypeScript-InterfaceInheritInterface
我们尝试让类继承自Interface:
interface Mover
{
move(): void;
}
class SimpleMover extends Mover{
move() {
alert("move")
}
}
var mover=new SimpleMover();
mover.move();
实践证明类是不能继承实现Interface的:A export class may only extend other classes, Mover is an interface.
现在大家知道TypeScript里的Interface和我们所认识和理解的接口的区别了吗?相同的一个名词Interface,不同语境下意义并不完全相同,看上去好像是挺傻的,但是学习和使用语言不做对比几乎是不可能的。
-
上一个: python文件输入输出操作
-
下一个: python中模块的学习笔记
相关文章
- PHP导出数据超时的优化建议解读 10-31
- PHP之mysql位运算解析 10-31
- Laravel实现登录跳转功能解析 10-31
- php双向队列解读 10-31
- Laravel异常上下文解决教程 10-24
- php数组查询元素位置方法介绍 10-24