質問

I'm just getting back to programming after a 20 year gap. I thought Python looked fairly straightforward and powerful, so I have done an online course and some reading.

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. 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. 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.

他のヒント

Your next step could be to use a class generated with the 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

Note that like tuple objects, namedtuple-derived objects are immutable. 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".

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. 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.

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).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top