Thursday, October 17, 2013

Partial function call

This post is part of the pyfun series, I will try to *log* some of the features that I think they make Python funny :)

Again, I was reading the Scala tutorial and find that she has built-in support of partial function call (see http://twitter.github.io/scala_school/basics.html#functions). This reminded me that Python does also has functools.partial(), which can be used as function shortcuts.

Let's see this example of Django.

# Let's have a Coupon that can either be fixed amount discount or percentage off
# But, we don't want to have model inheritance and table join to get the data
class Coupon(models.Model):
    code = models.CharField(max_length=8)
    type = models.CharField(max_length=11, choices=['fixedamount', 'percentage'])
    amount = models.DecimalField(max_digits=8, decimal_places=2)
    currency = models.CharField(max_length=3, choices=['USD', 'CAD'], default='')


# To create a Coupon based on certain conditions, you can have this
kwargs = {'code': code}

if condition_a:
    kwargs.update({'type': 'fixedamount', 'currency': 'USD'})
elif condition_b:
    kwargs.update({'type': 'percentage'})

kwargs.update({'amount': x if condition_c else y})
coupon = Coupon.objects.create(**kwargs)


# Or with functools.partial()
FixedamountCoupon = functools.partial(Coupon.objects.create, type='fixedamount')
PercentageCoupon = functools.partial(Coupon.objects.create, type='percentage')

if condition_a:
    coupon = functools.partial(FixedamountCoupon, code=code, currency='USD')
elif condition_b:
    coupon = functools.partial(PercentageCoupon, code=code)

coupon = functools.partial(coupon, amount=x if condition_c else y)
coupon = coupon()

Yes, we just shortcuted two types of Coupon using functools.partial(), created "sub-class" of Coupon. Furthermore, if the underlying function accepts positional arguments, we can also shortcut those arguments.

Clean code FTW.

Friday, October 11, 2013

Scala Traits in Python?

Sometimes, I would question myself, am I qualify as a seasoned Python engineer? The answer is I'm still a junior. The next question is, how to qualify as a seasoned one?

I have two things in mind that may be part of the answer to the second question:

1. Know when to use certain Python features.
2. Know what kind of library or framework is suitable for particular task.

In this pyfun series, I will try to *log* some of the features that I think they make Python funny :)

Let's get back to the primary subject of this post. Scala, which compiles to JAVA bytecode and runs on JVM, is one of the latest big hit. So, I'm going through some tutorials of it to check out her magics. One of the topic is Traits.

Traits, is similar to Java interface. When I read some samples about it, I wonder how can it be done in Python. From stackoverflow, http://stackoverflow.com/q/6240118, there is a suggestion that to use Python class to simulate the thing. And, starting from that idea, I wonder can we do that in runtime instead of just static definition. Here, we come to Python type().

Most of the time, type() can be used as Enum in C (see http://stackoverflow.com/a/1695250), or dynamic objects like those in Javascript (https://gist.github.com/mrkschan/6936112). It is because type() is essentially a dynamic form of the class statement (http://docs.python.org/2/library/functions.html#type). In other words, we can use type() to create Python class that simulates Traits (JAVA interface) at runtime.

Here is an example.

# See original Scala version at http://twitter.github.io/scala_school/basics.html#trait
Car = type('Car', (object,), {'brand': ''})
Shiny = type('Shiny', (object,), {'refraction': 0})

BMW = type('BMW', (Car, Shiny,), {'brand': 'BMW', 'refraction': 100})
my_bmw = BMW()

print my_bmw.brand, my_bmw.refraction

# We can have constructor as well
def bmw_init(self, refraction):
    self.refraction = refraction

BMW = type('BMW', (Car, Shiny,), {'brand': 'BMW', '__init__': bmw_init})
c1, c2 = BMW(10), BMW(100)
print c1.refraction, c2.refraction

As we can see, we can use type() to create a set of "interfaces". And, use type() to create class that implement the "interface". These "interfaces" can have its name changed according to runtime conditions. type() is Python magic and it's fun :)

However, I did not come up with a use case for runtime defined Traits yet :P
 
© 2009 Emptiness Blogging. All Rights Reserved | Powered by Blogger
Design by psdvibe | Bloggerized By LawnyDesignz