code critique requested - just 60 lines

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Thu Oct 2 12:02:42 EDT 2008


On Thu, 02 Oct 2008 07:51:30 -0700, Terrence Brannon wrote:

> Hi, I would like some feedback on how you would improve the following
> program:
> http://www.bitbucket.org/metaperl/ptc_math/src/21979c65074f/payout.py

Okay, I've read over the code, and tried to guess from context what it is 
supposed to do. I've added documentation (based on my guesses!) and 
modified the code in a few places. I've tried not to radically change the 
overall design of your code.

Some comments:

Readable is more important than concise. There's no prize for reducing 
the number of lines or leaving out comments.

I'm not really sure that your Scenario code gains much by being based on 
class instances. Perhaps ordinary functions would be easier to 
understand? That's probably a matter of taste though.

I don't consider it a good idea for __str__ to be used for complicated 
formatted results. In general, I would expect str(obj) to return a simple 
string version of the object. (Note that "simple" doesn't necessarily 
mean short.)

Your Rates class is simple enough that you could probably replace it with 
a plain tuple:

rates = {  # lookup table for standard and VIP payment rates.
    'std': (1, 0.5), 'vip': (1.25, 1.25)}

And then later in the code rates[member_type].per_click would become 
rates[member_type][0]. I wouldn't do that for more than two fields per 
record.

An even better idea would be the NamedTuple found here:
http://code.activestate.com/recipes/500261/

which is included in Python 2.6. For your simple purposes, the class Rate 
is probably good enough.



Here's my code, untested so there's no guarantee it will work. Also, 
because I'm lazy I haven't tried to fix long lines that have word-
wrapped, sorry.

I make no claim of copyright on the following, feel free to use it or 
discard it.

======

class Rates:
    """Record holding two fields.

    The fields are payment rates in cents per click and per
    referred(?) click. (FIXME : what is per_ref_click???)
    """
    def __init__(self, per_click, per_ref_click):
        self.per_click = per_click
        self.per_ref_click = per_ref_click

    def __str__(self):
        return '<Record: (%.2f, %.2f)>' % (self.per_click, 
self.per_ref_click)

ad_rate = 200 # 2 dollars for 100 clicks  FIXME: is this actually used?

rates = {  # lookup table for standard and VIP payment rates.
    'std': Rates(per_click=1, per_ref_click=0.5),
    'vip': Rates(per_click=1.25, per_ref_click=1.25)
        }

class Scenario:
    """Scenerio is a financial What-If calculation."""
    def __init__(self, std_clicks, vip_clicks, upline_status):
        """Initialise an instance with:
            std_clicks = the number of standard clicks to be paid (???)
            vip_clicks = the number of VIP clicks to be paid (???)
            upline_status = one of None, "std" or "vip"
        (but I don't know what the different statuses mean...)
        """
        self.clicks = {'std': std_clicks, 'vip' = vip_clicks}
        self.payout = {}
        self.ad_rate = 200
        self.upline_status = upline_status
        self.setup_payup()

    def setup_payup(self):
        """Set up the payout dictionary."""
        for member_type in rates:  # FIXME: should rates be global?
            self.payout[member_type] = self.clicks[member_type] * rates
[member_type].per_click
        if self.upline_status is None:
            self.payout['upline'] = 0
        else:
            self.payout['upline'] = sum(self.clicks.values()) * rates
[upline_status].per_ref_click

    def calc_profit(self):
        """Return the profit made."""
        return self.ad_rate - sum(self.payout.values())

    def display(self):
        """Pretty print a nicely formatted table of the scenario."""
        profit = self.calc_profit()
        template = """
Scenario: <no description>
===========================================================
Upline status:  %5s Upline payout:  %.1f
Std clicks:     %5d Std payout:     %.1f
VIP clicks:     %5d VIP payout:     %.1f
                     Profit:         %.1f
"""
        s = self  # alias to save space
        return template % (s.upline_status, s.payout['upline'],
            s.clicks['std'], s.payout['std'], s.clicks['vip'],
            s.payout['vip'], profit)



if __name__ == '__main__':
    # Set up some scenarios.
    scenarios = []
    for upline_status in [None, 'std', 'vip']:
        for vip_clicks in [0, 25, 50, 75, 100]:
            std_clicks = 100 - vip_clicks
            scenarios.append(
                Scenario(std_clicks, vip_clicks, upline_status)
                )
    # And display them.
    for s in scenarios:
        print s.display()





More information about the Python-list mailing list