Python currying with any number of variables

2024/11/16 21:29:13

I am trying to use currying to make a simple functional add in Python. I found this curry decorator here.

def curry(func):     def curried(*args, **kwargs):if len(args) + len(kwargs) >= func.__code__.co_argcount:return func(*args, **kwargs)return (lambda *args2, **kwargs2:curried(*(args + args2), **dict(kwargs, **kwargs2)))return curried@curry
def foo(a, b, c):return a + b + c

Now this is great because I can do some simple currying:

>>> foo(1)(2, 3)
6
>>> foo(1)(2)(3)
6

But this only works for exactly three variables. How do I write the function foo so that it can accept any number of variables and still be able to curry the result? I've tried the simple solution of using *args but it didn't work.

Edit: I've looked at the answers but still can't figure out how to write a function that can perform as shown below:

>>> foo(1)(2, 3)
6
>>> foo(1)(2)(3)
6
>>> foo(1)(2)
3
>>> foo(1)(2)(3)(4)
10
Answer

Arguably, explicit is better than implicit:

from functools import partialdef example(*args):print("This is an example function that was passed:", args)one_bound = partial(example, 1)
two_bound = partial(one_bound, 2)
two_bound(3)

@JohnKugelman explained the design problem with what you're trying to do - a call to the curried function would be ambiguous between "add more curried arguments" and "invoke the logic". The reason this isn't a problem in Haskell (where the concept comes from) is that the language evaluates everything lazily, so there isn't a distinction you can meaningfully make between "a function named x that accepts no arguments and simply returns 3" and "a call to the aforementioned function", or even between those and "the integer 3". Python isn't like that. (You could, for example, use a zero-argument call to signify "invoke the logic now"; but that would break special cases aren't special enough, and require an extra pair of parentheses for simple cases where you don't actually want to do any currying.)

functools.partial is an out-of-box solution for partial application of functions in Python. Unfortunately, repeatedly calling partial to add more "curried" arguments isn't quite as efficient (there will be nested partial objects under the hood). However, it's much more flexible; in particular, you can use it with existing functions that don't have any special decoration.

https://en.xdnf.cn/q/71295.html

Related Q&A

Python - Display rows with repeated values in csv files

I have a .csv file with several columns, one of them filled with random numbers and I want to find duplicated values there. In case there are - strange case, but its what I want to check after all -, I…

Defining __getattr__ and __getitem__ on a function has no effect

Disclaimer This is just an exercise in meta-programming, it has no practical purpose.Ive assigned __getitem__ and __getattr__ methods on a function object, but there is no effect...def foo():print &quo…

thread._local object has no attribute

I was trying to change the logging format by adding a context filter. My Format is like thisFORMAT = "%(asctime)s %(VAL)s %(message)s"This is the class I use to set the VAL in the format. cla…

Pytorch batch matrix vector outer product

I am trying to generate a vector-matrix outer product (tensor) using PyTorch. Assuming the vector v has size p and the matrix M has size qXr, the result of the product should be pXqXr.Example:#size: 2 …

Scraping Google Analytics by Scrapy

I have been trying to use Scrapy to get some data from Google Analytics and despite the fact that Im a complete Python newbie I have made some progress. I can now login to Google Analytics by Scrapy b…

Pandas representative sampling across multiple columns

I have a dataframe which represents a population, with each column denoting a different quality/ characteristic of that person. How can I get a sample of that dataframe/ population, which is representa…

TensorFlow - Ignore infinite values when calculating the mean of a tensor

This is probably a basic question, but I cant find a solution:I need to calculate the mean of a tensor ignoring any non-finite values.For example mean([2.0, 3.0, inf, 5.0]) should return 3.333 and not …

encode unicode characters to unicode escape sequences

Ive a CSV file containing sites along with addresses. I need to work on this file to produce a json file that I will use in Django to load initial data to my database. To do that, I need to convert all…

Python: Regarding variable scope. Why dont I need to pass x to Y?

Consider the following code, why dont I need to pass x to Y?class X: def __init__(self):self.a = 1self.b = 2self.c = 3class Y: def A(self):print(x.a,x.b,x.c)x = X() y = Y() y.A()Thank you to…

Python/Pandas - partitioning a pandas DataFrame in 10 disjoint, equally-sized subsets

I want to partition a pandas DataFrame into ten disjoint, equally-sized, randomly composed subsets. I know I can randomly sample one tenth of the original pandas DataFrame using:partition_1 = pandas.Da…