[Python-ideas] Optional static typing -- the crossroads

Steven D'Aprano steve at pearwood.info
Sun Aug 17 04:08:51 CEST 2014


On Sat, Aug 16, 2014 at 01:22:48PM -0700, Ethan Furman wrote:

> As a test case for what code may soon look like, here's a bit from one of 
> my code bases:
> 
> 
> --------------------------------------------------------------------
> class ACHPayment(object):
>     """A single payment from company to a vendor."""
> 
>     def __init__(self,
>             description, sec_code,
>             vendor_name, vendor_inv_num, vendor_rtng, vendor_acct,
>             transaction_code, vendor_acct_type, amount, payment_date):
>         """
>         description:  10 chars
>         sec_code: 'CCD' or 'CTX'
>         vendor_name: 22 chars
>         vendor_inv_num: 15 chars
>         vendor_rtng: 9 chars
>         vendor_acct: 17 chars
>         transaction_code: ACH_ETC code (enum)
>         vendor_acct_type: 'domestic' or 'foreign'
>         amount: 10 digits (pennies)
>         payment_date: date payment should occur on (datetime.date type 
>         class)
>         """
> --------------------------------------------------------------------
> 
> 
> The question:  what would this look like with type annotations?  As a point 
> of interest, the last parameter, payment_date, can be /anything/ that 
> quacks like a datetime.date -- I tend to use my own dbf.Date class, which 
> subclasses object, not datetime.date itself.


I don't think this is a shining example of the value of static typing, 
at least not by default. As I see it, you would get something like this:

    def __init__(self,
            description:str, sec_code:str,
            vendor_name:str, vendor_inv_num:str, 
            vendor_rtng:str, vendor_acct:str, 
            transaction_code:str, vendor_acct_type:str, 
            amount:int, payment_date:Any)->None:

which may not give you much additional value. In this case, I think that 
the static checks will add nothing except (perhaps) allow you to forgo 
writing a few isinstance checks. You still have to check that the 
strings are the right length, and so on.

But if you're willing to invest some time creating individual str 
subclasses, you can push the length checks into the subclass 
constructor, and write something like this:

    def __init__(self,
            description:Str10, sec_code:SecurityCode,
            vendor_name:Str22, vendor_inv_num:Str15, 
            vendor_rtng:Str9, vendor_acct:Str17, 
            transaction_code:ACH_ETC, vendor_acct_type:VendorAcctType, 
            amount:Pennies, payment_date:DateABC)->None:

Without knowing your application in detail, it is difficult to know how 
much work you should hand over to the type system, and how much you 
should continue to do in Python. If all you're doing is pushing strings 
from one place to another, you might not care exactly how long the 
string is, say because they're truncated when you print them.



-- 
Steven


More information about the Python-ideas mailing list