简体   繁体   English

Python面向对象的设计概念

[英]Python object oriented design concepts

I'm just getting back to programming after a 20 year gap. 我只是在20年的差距后回到编程。 I thought Python looked fairly straightforward and powerful, so I have done an online course and some reading. 我认为Python看起来相当简单和强大,所以我做了一个在线课程和一些阅读。

I'm now looking at some simple projects to get familiar with the language. 我现在正在看一些简单的项目来熟悉这门语言。 One of the challenges is getting my head around object oriented programming, which was not around when I last wrote a program. 其中一个挑战是围绕面向对象的编程,这在我上次编写程序时并不存在。

My first project was to read in a data file containing information about a share portfolio, do some calculations on each and print a report. 我的第一个项目是读取包含有关股票投资组合信息的数据文件,对每个投资组合进行一些计算并打印报告。 I have this working. 我有这个工作。

So now I am looking at something more advanced, reading in the data and storing it, then using the data to provide answers to interactive questions. 所以现在我正在寻找更先进的东西,读取数据并存储它,然后使用数据来提供交互式问题的答案。 My question is how to store the data so it can be accessed easily. 我的问题是如何存储数据,以便轻松访问。

My first thought was to make a list of lists, eg, 我的第一个想法是列出一个列表,例如,

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

This can be accessed in loops easily enough, but the access methods are not exactly friendly - numbers as indexes instead of names: 这可以在循环中轻松访问,但访问方法并不完全友好 - 数字作为索引而不是名称:

companyqty = companies[1][1]

Or for loops: 或者循环:

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

Then I thought about a dictionary, with the value being a list: 然后我想到了一本字典,其值为列表:

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

This provides immediate access to any given company, but is still stuck with the numeric indexes. 这提供了对任何给定公司的即时访问,但仍然停留在数字索引中。

So I am wondering how to structure this in an object oriented manner so as to be able to hold a list of companies and all the associated data, and be able to access the values conveniently. 所以我想知道如何以面向对象的方式构建它,以便能够保存公司列表和所有相关数据,并能够方便地访问这些值。 All my ideas so far just look like lists or dictionaries as above. 到目前为止,我的所有想法看起来都像上面的列表或词典。

Or is this sort of problem not really suited to an object oriented approach? 或者这种问题不适合面向对象的方法吗?

Thanks 谢谢

This is a fine problem for an OOP approach. 对于OOP方法来说,这是一个很好的问题。 You could, for example, create a class for a particular portfolio stock holding, which has attributes for the company name, number of shares, and share price. 例如,您可以为特定投资组合库存创建一个类,该类具有公司名称,股票数量和股价的属性。 You can give it useful functions, like getValue . 你可以给它有用的功能,比如getValue Here's an example implementation: 这是一个示例实现:

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

You can access the attributes of your holdings by attribute name. 您可以按属性名称访问所有馆藏的属性。 You could take it to the next level, and write a class for portfolio, too, which could have attributes like "holdingList", and "broker name", and functions like "getTotalValue", and so forth. 您可以将它带到下一个级别,并为组合编写一个类,它可能具有“holdingList”和“broker name”等属性,以及“getTotalValue”等函数,等等。

Your next step could be to use a class generated with the collections.namedtuple() factory : 您的下一步可能是使用使用collections.namedtuple()工厂生成的类:

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

Note that like tuple objects, namedtuple -derived objects are immutable. 请注意,与tuple对象一样, namedtuple -derived对象也是不可变的。 You cannot assign to the attributes, you'd create a new object instead. 您无法分配属性,而是创建新对象。

You'd only need to switch to custom classes if you needed to add functionality to your objects; 如果需要为对象添加功能,则只需要切换到自定义类; add methods that act on the data associated with an object: 添加作用于与对象关联的数据的方法:

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

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

you could also use nested dictionaries: 你也可以使用嵌套的词典:

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

and access it like: 并访问它像:

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

you even could define extra "properties" for company: 你甚至可以为公司定义额外的“属性”:

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'}
   }

Even so in Python there is one and only one way to do things, the answer to this question really depends on what is "can be accessed easily". 即便如此,在Python中只有一种方法可以做到,这个问题的答案实际上取决于“可以轻松访问”的内容。

Does it mean, that it is easy for a programmer to access an object and it's attribute? 这是否意味着,程序员很容易访问对象及其属性? Then the best way is to make Company an instance of the class and provide atributes for price, quantity, etc. Probably, it's overkill to make class called Portfolio, unless you will have non-trivial logic apart from that of the list or dict. 那么最好的方法是让公司成为一个类的实例,并提供价格,数量等的属性。可能,将类称为Portfolio是不合适的,除非你将具有除列表或词典之外的非平凡逻辑。 It is also possible to make the class based on a dictionary, so both access by keys and attributes will be possible. 也可以基于字典来创建类,因此可以通过键和属性进行访问。 This is what I would call accessed easily. 这就是我所说的轻松访问的内容。 Take a look at the Storage class of webpy framework: https://github.com/webpy/webpy/blob/master/web/utils.py#L52 as an example. 看一下webpy框架的Storage类: https//github.com/webpy/webpy/blob/master/web/utils.py#L52作为示例。

If "accessed easily" means some serialization or other processing will be done to the data by third party library, then the easiest way is to use data structures, expected by the library. 如果“轻松访问”意味着第三方库将对数据进行一些序列化或其他处理,那么最简单的方法是使用库所期望的数据结构。 For example, JSON format maps very well with Python's lists and dictionaries (see the answer by Roman Pekar). 例如,JSON格式可以很好地映射Python的列表和字典(参见Roman Pekar的答案)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM