面向对象设计与面向对象编程的关系
面向对象设计(OOD)不会特别要求面向对象编程语言。事实上,OOD 可以由纯结构化语言来实现,比如 C,但如果想要构造具备对象性质和特点的数据类型,就需要在程序上作更多的努力。当一门语言内建 OO 特性,OO 编程开发就会更加方便高效。另一方面,一门面向对象的语言不一定会强制你写 OO 方面的程序。例如 C++可以被认为"更好的C";而 Java,则要求万物皆类,此外还规定,一个源文件对应一个类定义。然而,在 Python 中,类和 OOP 都不是日常编程所必需的。尽管它从一开始设计就是面向对象的,并且结构上支持 OOP,但Python 没有限定或要求你在你的应用中写 OO 的代码。OOP 是一门强大的工具,不管你是准备进入,学习,过渡,或是转向 OOP,都可以任意支配。考虑用 OOD 来工作的一个最重要的原因,在于它直接提供建模和解决现实世界问题和情形的途径。
类
类是一种数据结构,我们可以用它来定义对象,后者把数据值和行为特性融合在一起。类是现实世界的抽象的实体以编程形式出现。实例是这些对象的具体化。可以类比一下,类是蓝图或者模型,用来产生真实的物体(实例)。类还可以派生出相似但有差异的子类。编程中类的概念就应用了很多这样的特征。在 Python 中,类声明与函数声明很相似,头一行用一个相应的关键字,接下来是一个作为它的定义的代码体,如下所示:
复制代码 代码如下:
def functionName(args):
'function documentation string' #函数文档字符串
function_suite #函数体
class ClassName(object):
'class documentation string' #类文档字符串
class_suite #类体
二者都允许你在他们的声明中创建函数,闭包或者内部函数(即函数内的函数),还有在类中定义的方法。最大的不同在于你运行函数,而类会创建一个对象。类就像一个 Python 容器类型。尽管类是对象(在 Python 中,一切皆对象),但正被定义时,它们还不是对象的实现。
创建类
Python 类使用 class 关键字来创建。简单的类的声明可以是关键字后紧跟类名:
复制代码 代码如下:
class ClassName(bases):
'class documentation string' #'类文档字符串'
class_suite #类体
基类是一个或多个用于继承的父类的集合;类体由所有声明语句,类成员定义,数据属性和函数组成。类通常在一个模块的顶层进行定义,以便类实例能够在类所定义
的源代码文件中的任何地方被创建。
声明与定义
对于 Python 函数来说,声明与定义类没什么区别,因为他们是同时进行的,定义(类体)紧跟在声明(含 class 关键字的头行[header line])和可选的文档字符串后面。同时,所有的方法也必须同时被定义。如果对 OOP 很熟悉,请注意 Python 并不支持纯虚函数(像 C++)或者抽象方法(如在 JAVA 中),这些都强制程序员在子类中定义方法。作为替代方法,你可以简单地在基类方法中引发 NotImplementedError 异常,这样可以获得类似的效果。
类属性
属性就是属于另一个对象的数据或者函数元素,可以通过我们熟悉的句点属性标识法来访问。一些 Python 类型比如复数有数据属性(实部和虚部),而另外一些,像列表和字典,拥有方法(函数属性)。
有关属性的一个有趣的地方是,当你正访问一个属性时,它同时也是一个对象,拥有它自己的属性,可以访问,这导致了一个属性链,比如,myThing,subThing,subSubThing.等等
类的数据属性
数据属性仅仅是所定义的类的变量。它们可以像任何其它变量一样在类创建后被使用,并且,要么是由类中的方法来更新,要么是在主程序其它什么地方被更新。
这种属性已为 OO 程序员所熟悉,即静态变量,或者是静态数据。它们表示这些数据是与它们所属的类对象绑定的,不依赖于任何类实例。如果你是一位 Java 或 C++程序员,这种类型的数据相当于在一个变量声明前加上 static 关键字。静态成员通常仅用来跟踪与类相关的值。
看下面的例子,使用类数据属性(foo):
复制代码 代码如下:
class c(object):
foo = 100
print c.foo
100
c.foo+=1
c.foo
101
方法
复制代码 代码如下:
class MyClass(object):
def myNoActionMethod(self):
pass
mc = MyClass()
mc.myNoActionMethod()
任何像函数一样对 myNoActionMethod 自身的调用都将失败:
复制代码 代码如下:
myNoActionMethod() Traceback (innermost last):
File "", line 1, in ?
myNoActionMethod() NameError: myNoActionMethod
甚至由类对象调用此方法也失败了。
复制代码 代码如下:
MyClass.myNoActionMethod() Traceback (innermost last):
File "", line 1, in ?
MyClass.myNoActionMethod()
TypeError: unbound method must be called with class
instance 1st argument
绑定(绑定及非绑定方法)
为与 OOP 惯例保持一致,Python 严格要求,没有实例,方法是不能被调用的。这种限制即 Python所描述的绑定概念(binding),在此,方法必须绑定(到一个实例)才能直接被调用。非绑定的方法可能可以被调用,但实例对象一定要明确给出,才能确保调用成功。然而,不管是否绑定,方法都是它所在的类的固有属性,即使它们几乎总是通过实例来调用的。
决定类的属性
要知道一个类有哪些属性,有两种方法。最简单的是使用 dir()内建函数。另外是通过访问类的字典属性dict,这是所有类都具备的特殊属性之一。
看一下下面的例子:
复制代码 代码如下:
class myclass(object):
'myclass class definition' #类定义
myVersion = '1.1' #静态数据
def showVesion(self): #方法
print myclass.myVersion
dir(myclass)
运行结果:
复制代码 代码如下:
['class', 'delattr', 'dict', 'doc', 'format', 'getattribute', 'hash', 'init', 'module', 'new', 'reduce', '__reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook', 'weakref__', 'myVersion', 'showVesion']
使用:
复制代码 代码如下:
myclass.dict
dict_proxy({'module': 'main', 'showVesion': <function showVesion at 0x0134C9B0>, 'dict': <attribute 'dict' of 'myclass' objects>, 'myVersion': '1.1', 'weakref': <attribute 'weakref' of 'myclass' objects>, 'doc': 'myclass class definition'})
从上面可以看到,dir()返回的仅是对象的属性的一个名字列表,而dict返回的是一个字典,它的键(keys)是属性名,键值(values)是相应的属性对象的数据值。
结果还显示了 MyClass 类中两个熟悉的属性,showMyVersion 和 myVersion,以及一些新的属性。这些属性,doc及module,是所有类都具备的特殊类属性(另外还有dict)。。内建的 vars()函数接受类对象作为参数,返回类的dict属性的内容。
特殊的类属性
对任何类C,表显示了类C的所有特殊属性:
C.name 类C的名字(字符串)
C.doc 类C的文档字符串
C.bases 类C的所有父类构成的元组
C.dict 类C的属性
C.module 类C定义所在的模块(1.5 版本新增)
C.class 实例C对应的类(仅新式类中)
复制代码 代码如下:
myclass.name
'myclass'
myclass.doc
'myclass class definition'
myclass.bases
(<type 'object'>,)
print myclass.dict
{'module': 'main', 'showVesion': <function showVesion at 0x0134C9B0>, 'dict': <attribute 'dict' of 'myclass' objects>, 'myVersion': '1.1', 'weakref': <attribute 'weakref' of 'myclass' objects>, 'doc': 'myclass class definition'}
myclass.module
'main'
myclass.class
<type 'type'>
实例
如果说类是一种数据结构定义类型,那么实例则声明了一个这种类型的变量。实例是那些主要用在运行期时的对象,类被实例化得到实例,该实例的类型就是这个被实例化的类。
初始化:通过调用类对象来创建实例
Python 的方式更加简单。一旦定义了一个类,创建实例比调用一个函数还容易------不费吹灰之力。实例化的实现,可以使用函数操作符,如下示:
class MyClass(object): # define class 定义类
pass
mc = MyClass() # instantiate class 初始化类
init()"构造器"方法
当类被调用,实例化的第一步是创建实例对象。一旦对象创建了,Python 检查是否实现了init()方法。默认情况下,如果没有定义(或覆盖)特殊方法init(),对实例不会施加任何特别的操作.任何所需的特定操作,都需要程序员实现init(),覆盖它的默认行为。
如果init()没有实现,则返回它的对象,实例化过程完毕。
如果init()已经被实现,那么它将被调用,实例对象作为第一个参数(self)被传递进去,像标准方法调用一样。调用类时,传进的任何参数都交给了init()。实际中,你可以想像成这样:把创建实例的调用当成是对构造器的调用。
new()"构造器"方法
与init()相比,new()方法更像一个真正的构造器。需要一种途径来实例化不可变对象,比如,派生字符串,数字,等等。在这种情况下,解释器则调用类的new()方法,一个静态方法,并且传入的参数是在类实例化操作时生成的。new()会调用父类的new()来创建对象(向上代理)。new()必须返回一个合法的实例。
del()"解构器"方法
同样,有一个相应的特殊解构器(destructor)方法名为del()。然而,由于 Python 具有垃圾对象回收机制(靠引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才会执行。Python 中的解构器是在实例释放前提供特殊处理功能的方法,它们通常没有被实现,因为实例很少被显式释放。
注意:Python 没有提供任何内部机制来跟踪一个类有多少个实例被创建了,或者记录这些实例是些什么东西。如果需要这些功能,你可以显式加入一些代码到类定义或者init()和del()中去。最好的方式是使用一个静态成员来记录实例的个数。靠保存它们的引用来跟踪实例对象是很危险的,因为你必须合理管理这些引用,不然,你的引用可能没办法释放(因为还有其它的引用)!看下面一个例子:
复制代码 代码如下:
class instCt(object):
count = 0
def init(self):
instCt.count += 1
def del(self):
instCt.count -= 1
def howMany(self):
return instCt.count
a = instCt()
b = instCt()
b.howMany()
2
a.howMany()
2
del b
a.howMany()
1
del a
instCt.count
0
实例属性
设置实例的属性可以在实例创建后任意时间进行,也可以在能够访问实例的代码中进行。构造器init()是设置这些属性的关键点之一
能够在"运行时"创建实例属性,是 Python 类的优秀特性之一,Python 不仅是动态类型,而且在运行时,允许这些对象属性的动态创建。这种特性让人爱不释
手。当然,创建这样的属性时,必须谨慎。一个缺陷是,属性在条件语句中创建,如果该条件语句块并未被执行,属性也就不存在,而你在后面的代码中试着去访问这些属性,就会有错误发生。
默认参数提供默认的实例安装
在实际应用中,带默认参数的init()提供一个有效的方式来初始化实例。在很多情况下,默认值表示设置实例属性的最常见的情况,如果提供了默认值,我们就没必要显式给构造器传值了。
复制代码 代码如下:
class HotelRoomCalc(object):
'hotel room rate calculate'
def init(self, rt, sales = 0.085, rm = 0.1):
'''HotelRoomCalc default arguments:
sales tax == 8.5% and room tax == 10%'''
self.salesTax = sales
self.roomTax = rm
self.roomRate = rt
def calcTotal(self, days = 1):
'Calculate total: default to daily rate'
daily = round((self.roomRate 14 (1+self.roomTax + self.salesTax)),2)
return float(days) * daily
sfo = HotelRoomCalc(299)
sfo.calcTotal()
4960.41
sfo.calcTotal(2)
9920.82
sea = HotelRoomCalc(189, 0.086, 0.085)
sea.calcTotal()
3098.47
sea.calcTotal(4)
12393.88
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。