2013-08-17 124 views
4

我只是在20年的差距后重新开始编程。我认为Python看起来相当直接和强大,所以我完成了在线课程和一些阅读。Python面向对象的设计概念

我现在正在看一些简单的项目,以熟悉该语言。其中一个挑战就是让我的头脑围绕着面向对象的编程,而当我最后编写一个程序时,它并不在我身边。

我的第一个项目是读取包含股票投资组合信息的数据文件,对每个项目进行一些计算并打印报告。我有这个工作。

所以现在我正在寻找更高级的东西,阅读数据并存储它,然后使用数据为互动问题提供答案。我的问题是如何存储数据,以便可以轻松访问。

我首先想到的是让一个列表的列表,如

companies = [ ['AMP', 1000, 2.50], ['ANZ', 2000, 17.00], ['BHP', 500, 54.30] ] 

这可以在循环很轻松地访问,但是访问方法都算不上友好 - 数字作为指标而不是名称:

companyqty = companies[1][1] 

或者for循环:

for company in companies: 
    if company[0] == 'BHP': 
     companyqty = company[1] 

然后我想到了一本字典,与价值列表:

companies = {'AMP':[1000, 2.50], 'ANZ':[2000, 17.00], 'BHP':[500, 54.30] } 
companyqty = companies['BHP'][0] 

这提供了即时访问任何给定的公司,但仍然坚持与数字指标。

所以我想知道如何以面向对象的方式来构造这个结构,以便能够保存公司列表和所有关联的数据,并且能够方便地访问这些值。到目前为止,我所有的想法都像上面的列表或字典一样。或者这种问题不是真的适合面向对象的方法吗?

感谢

回答

4

这是OOP方法的一个很好的问题。例如,您可以为特定投资组合股票持有创建一个类别,该类别具有公司名称,股份数量和股价的属性。你可以给它有用的功能,如getValue。下面是一个示例实现:

class Holding: 
    def __init__(self, companyName, numShares, sharePrice): 
     self.companyName = companyName 
     self.numShares = numShares 
     self.sharePrice = sharePrice 
    def getValue(self): 
     return self.numShares * self.sharePrice 

portfolio = {'AMP':Holding('AMP', 1000, 2.5), 'ANZ':Holding('ANZ', 2000, 17.0), 'BHP':Holding('BHP', 500, 54.30)} 

print portfolio['BHP'].sharePrice 
# 54.3 
print portfolio['AMP'].getValue() 
# 2500.0 

您可以通过属性名称访问您持有的属性。你可以把它提升到一个新的水平,并为投资组合编写一个类,它可能具有诸如“holdingList”和“broker name”之类的属性,以及诸如“getTotalValue”之类的函数等等。

3

你下一步可以使用与collections.namedtuple() factory产生的一类:

from collections import namedtuple 

Company = namedtuple('Company', 'quantity price') 

companies = {'AMP': Company(1000, 2.50), 'ANZ': Company(2000, 17.00), 'BHP': Company(500, 54.30)} 

companies['AMP'].quantity 

注意,喜欢tuple对象,namedtuple衍生的对象是不可改变的。您不能指定属性,而是创建一个新对象。

如果您需要为对象添加功能,则只需切换到自定义类;添加作用于与对象关联的数据的方法:

class Company(object): 
    def __init__(self, quantity, price): 
     self.quantity = quantity 
     self.price = price 

    def profit(self, newprice): 
     return self.quantity * (newprice - self.price) 
1

你也可以使用嵌套的字典:

companies = 
    { 
     'AMP': {'quantity':1000, 'price': 2.50}, 
     'ANZ': {'quantity':2000, 'price': 17.00}, 
     'BHP': {'quantity':500, 'price': 54.30} 
    } 

和访问它想:

companyqty = companies['BHP']['quantity'] 

,你甚至可以定义额外的 “属性” 公司:

companies = 
    { 
     'AMP': {'quantity':1000, 'price': 2.50, 'foundation_date': '2013-01-01'}, 
     'ANZ': {'quantity':2000, 'price': 17.00}, 
     'BHP': {'quantity':500, 'price': 54.30, 'head': 'Jeffrey'} 
    } 
0

即使如此在Python中,只有一种方法可以做到,这个问题的答案实际上取决于什么是“可以访问” sed容易“。

这是否意味着程序员访问对象很容易,它的属性?那么最好的办法就是让公司成为一个类的实例,并为价格,数量等提供属性。可能,把类叫做投资组合是一件很矫枉过正的事,除非你的列表或字典的逻辑不同。也可以基于字典创建类,因此可以通过键和属性进行访问。这就是我所称的访问轻松。以Webpy框架的Storage类为例:https://github.com/webpy/webpy/blob/master/web/utils.py#L52为例。

如果“容易访问”意味着第三方库将对数据进行一些序列化或其他处理,那么最简单的方法是使用库预期的数据结构。例如,JSON格式与Python的列表和字典非常吻合(请参阅Roman Pekar的答案)。

+0

我想我真正的意思是以最小化错误可能性的方式访问,特别是使用数字引用字段(例如Companies [1] [1])。在我的第一个练习中,我多次出手。我想我仍然在考虑从1开始而不是从0开始的索引。通过使用名称,我避免了这种情况。 –

+0

是的,我甚至没有考虑过使用数字键,因为使用键或属性会使格式携带它的上下文。如果出于某种外部原因必须使用列表或元组中的位置,则可以为位置定义名称,例如,公司[0] [COMPANY_PRICE。在其中一个答案中也提到了名称。 –