String that is initialized lazily in Python - python

I figured out that with deriving from str and overwriting __new__ you can overwrite strings. Do you know any magic that would create a lazily initialized string?
Therefore
def f(a, b):
print("f called")
return a+b
s=f("a", "b")
print("Starting")
print(s)
how can I add a decorator to the function f such that this function is executed only after "Starting" was printed (basically on first access)? Seems tricky... :)
I can do it when objects are returned, because there I intercept attribute access. However, string doesn't use attribute access?

There may be simpler ways of doing what you want --
However, I once wrote a generic "lazy decorator" for generic functions that does exactly what you are asking for -- perceive it is more complicated exactly because it would work for almost any kind of object returned by the functions.
The basic idea is: for a given exiting object, Python does not actually "use" its value but for callingone of the "dunder' (magic double "__" ) methods in the object's class -
be it for representing it ( calls either __repr__ __str__ __unicode__) getting attributes from it, making calls, usiogn it as an operator in an arithmetic operation and so on.
So, this decorator, when the function is called, basically stores the parameters and wait for any of these magic methods to be called, whereupon it does make the originall call and caches the return value -
The soruce code is here:
https://github.com/jsbueno/metapython/blob/main/lazy_decorator.py

The attributes you're looking for are __str__(), __repr__(), and __unicode__().

Try using the LazyString class from stringlike, like this
from stringlike.lazy import LazyString
def f(a, b):
print("f called")
return a+b
s = LazyString(lambda: f("a", "b"))
print("Starting")
print(s)

Related

Difference between functions and methods in Python

I can't seem to understand the difference between methods and functions.
From my knowledge I am aware that methods are functions that are unique to the classes they are implemented in, but for functions can I say that they can be used in general and are not restricted to a certain class. Also, is the indentation of functions vs methods another essential difference? As methods are implemented within classes and functions are outside with the least indentation.
A function is virtually the same as a method only that the latter is bound to a class. In Python, in most cases, the same way you define a function is the same way you define a method. However, to refer to the class it is in, you will at times see the 'self' parameter added to the method as in: def function_name(self):. The indentation works similarly in both cases.
I think the reason why you tend to think that the indentation of a method is deeper than that of a function is because by the time you're writing your method, you are already indented inside the class.
Python, in particular, across most programming languages, really does not differentiate much between functions and methods.
What you declare is true: "methods are functions that are unique to the classes they are implemented in" -
And that makes for the indentation difference: since methods are inside a class, they are indented inside the class statement block.
When you create a simple class, and retrieve a method from it directly, it is actually a function (in python 3 - it worked differently in old Python 2.x):
from types import FunctionType
class A:
def b(self):
pass
print(A.b, type(A.b) is FunctionType)
Prints:
<function A.b at 0x...> True
So, in Python, a "method" is really and literally a function!
It will work differently when retrieved from an instance of the class it is declared on.
[optional complicated paragraph] Then, Python wraps it with what can be described as "a lazy object callable that will insert the instance it is bound to as first argument to the underlying function when called." Once you can make sense of this phrase, you can check "seasoned Pythonista" in your CV.
What it means is simply that "self" will appear "magically" when calling the method, and moreover, one can go back to the original function by looking at the method's .__func__ attribute.
So, given the same class A above:
In [52]: print(A().b, type(A().b), type(A().b) is FunctionType)
<bound method A.b of <__main__.A object at 0x...>> <class 'method'> False
In [53]: print(A().b.__func__, type(A().b.__func__), type(A().b.__func__) is FunctionType)
<function A.b at 0x...> <class 'function'> True
Note that in these examples I instantiate a new object of the class A at each time, by writing A(), while in the first example, I retrieve b directly from the class, without parenthesis: A.b
As I stated in the beggining of the text: be aware that the fact a plain function can be used as a method is particular to Python, and both kinds of objects will likely have some differences in other programming languages. The idea however, will remain the same: a method will always "know" about the instance from where it was retrieved.

Can I use a function passed by parameters?

I have a function, and inside this function I should execute another function of 3 posibilities.
The simple way should be passing a parameter, doing a if-elif to exec function acording to that parameter, but I'd like to know it it's posible to pass the name of a funtion by params and use that, something like:
FunctionA(Param1, Param2, FunctionNameToUse)
....Code....
FunctionNameToUse(Value1, Value2)
....Code....
endFunctionA
Depending on how functionA is called, it will use one Function or another, I dont know if I explained well...
Thanks mates!
Functions themselves are first class objects in Python. So there's no need to pass the name: pass the actual function itself, then you can call it directly.
def func1(a, b):
pass
def func2(a, b):
pass
def functionA(val1, val2, func):
func(val1, val2)
# now call functionA passing in a function
functionA("foo", "bar", func1)
In python, functions are first-class values, which means they can be passed around as arguments, returned from functions, and so on.
So the approach you want to take should work (However you're not passing the name, you're passing the actual function).
Take a look at map and filter in the standard library, they do exactly this.
Yes, you can. As other have mentioned, functions are first-class objects, i.e. you can do everything you can think of to it (see What are "first class" objects? for more info).
So then, how does this really work when you pass in a function as parameter? If you have taken any ComSci class, you'd know that each process has a special area in memory allocated for its code; all of your functions are defined here. Whenever you call a function, the CPU would move the Program Counter (a special pointer that points to whatever code it is executing at the moment) to the beginning of that function's code, and go from there. Thus, after the function is loaded in memory, all that's needed to call it is its address. When you pass a function A's "name" as an argument to another function B in Python, what you are doing is really passing a reference (in C term, a pointer) that contains the address to the code that represents A in memory.

Why are parenthesis optional when defining a class, but mandatory when defining a function?

In Python, defining a function with an empty parameter list requires a set of empty parenthesis. However, defining a class with the default superclass does not require a set of empty parenthesis; rather, those are optional, and appear to be uncommon. Why is it so?
See also: Python class definition syntax.
I think the answer to your question is simply syntax. That is just the way Python is set up, but my take on how it got that way is:
I would think functions came out of mathematics things like:
f(x) = x
So when computer programming languages were being created there seems to have been some logical continuity from analog mathematics into programming languages.
Classes on the other hand are more constructs of Computer Science, and repetitive memory management, so they were not created in such a fashion, but because they have a functional quality to them, they were given similar notation.
For Python, I will use the term method for function as that is the usual lingo...
I understand your argument that both a class and method should be allowed to be defined using a short-cut in the no argument case:
for classes when there is no inheritence
for methods when there are no arguments
One reason I can think of is for consistency across usage and definition. Let's look at some examples:
definition:
def funcA():
return 0
def funcB(arg):
return arg
and you want to call that funciton:
>>> funcA()
>>> functB("an argument")
and
>>> f1 = funcA
>>> f2 = funcB
>>> f1()
>>> f2("another argument")
to pass references and call them.
The syntax of the paranthesis between method declaration is consistent with calling the methods.
You need to put those empty parenthesis otherwise the interpreter will give you a reference to the method, and not actually call it.
So one benefit is it makes your code very clear.
definition:
class classA:
pass
class classB(object):
pass
usage:
# create an instance
my_instance_of_A = classA()
my_instance_of_B = classB()
# pass a reference
my_ref_to_A = classA
my_ref_to_B = classB
# call by reference
new_A = my_ref_to_A()
new_B = my_ref_to_B()
Here there is no change in behavior with regards to whether the class inherits or not, its calling behavior is dictated by what its internal or inherited __init__ method is defined as.
I think the current set up of requiring the empty () makes the code more readable to the untrained eye.
If you really really really want to do what you ask, there is a workaround... you could always do this:
func = lambda: "im a function declared with no arguments, and I didn't use parenthesis =p"
which can be called:
>>> func
<function <lambda> at 0x6ffffef26e0>
>>> func()
"im a function declared with no arguments, and I didn't use parenthesis =p"
But the python holy book says No

Why do functions/methods in python need self as parameter? [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 8 years ago.
I can understand why it is needed for local variables, (self.x), but why is is nessecary as parameter in a function? Is there something else you could put there instead of self?
Please explain in as much layman terms as possible, I never had decent programming education.
By default, every function declared in the namespace of a class assumes that its first argument will be a reference to an instance of that class. (Other types of functions are decorated with #classmethod and #staticmethod to change this assumption.) Such functions are called methods. By convention, Python programmers name that first parameter self, but Python doesn't care what you call it. When a method is called, you must provide that reference. For example (with self replaced by foobar to demonstrate that self is not the required name):
class A:
def __init__(foobar):
foobar.x = 5
def somefunc(foobar, y):
print foobar.x + y
a = A()
print A.somefunc(a, 3) # Prints 8
Python provides some syntactic sugar to make the link between an object and a method called on it more obvious, by letting you call a bound method instead of the function itself. That is, a.somefunc(3) and A.somefunc(a, 3) are equivalent. In Python terminology, A.somefunc is an unbound method, since it still needs an instance when it is called:
f = A.somefunc
print f(a, 3)
By contrast, a.somefunc is called a bound method, since you have already provided the instance to use as the first argument:
f = a.somefunc
print f(3)
If you consider it, EVERY programming language does that - or, at least, the most common languages like pascal, c++ or java do). EXCEPT that, in most programming languages, the this keyword is assumed and not passed as a parameter. Consider the function pointers in those languages: they're different than method-pointers.
Pascal:
function(a: Integer): Integer;
vs
function(a: Integer): Integer of object;
The latter considers the self pointer (yes, it's named self but it's an implicit pointer like the this in c++, while the python self is explicit).
C++:
typedef int (*mytype)(int a);
vs
typedef int Anyclass::(*mytype)(int a);
As difference with Pascal, in C++ you must specify the class owning the method. Anyway, this method pointer declaration states the difference between a function expecting a this or not.
But Python takes seriously it's Zen, as quichua people takes seriously their Ama Suway, Ama Llullay, Ama K'ellay:
Explicit is better than implicit.
So, that's why you see explicitly the self parameter (and must write it, of course) for instance methods and #classmethods (althought it's usually called cls there since it's intention is to dynamically know the class and not the instance). Python does not assume a this or self keyword must exist inside the methods (so, the namespace has only true variables - remember you are NOT forced to name them self or cls althought it's usual and expected).
Finally, if you get:
x = AClass.amethod #unbound method
You must call it as
x(aninstance, param, param2, ..., named=param, named2=param2, ...)
While getting it as:
x = anInstance.method #bound method, has `im_self` attribute set to the instance.
must be called as:
x(param, param2, ..., named=param, named2=param2, ...)
Yes, the self is explicit in the parameter list since it's not assumed a keyword or 'backdoor' must exist, but not in the argument list because of syntactic sugar every OOP language has (weird criteria, huh?).
It's how Python's implementation of object oriented programming works -- a method of an instance (a so-called bound method) is called with that instance as its first argument.
Besides variables of the instance (self.x) you can also use it for anything else, e.g. call another method (self.another_method()), pass this instance as a parameter to something else entirely (mod.some_function(3, self)), or use it to call this method in the superclass of this class (return super(ThisClass, self).this_method()).
You can give it an entirely different name as well. Using pony instead of self will work just as well. But you shouldn't, for obvious reasons.
The use of self for the first reference in a method is entirely convention.
You can call it something else, even inconsistently in the same class:
class Foo(object):
def __init__(notself, i):
notself.i=i # note 'notself' instead of 'self'
def __str__(self):
return str(self.i) # back to the convention
f=Foo(22)
print f
But please don't do that. It is confusing to others that may read your code (or yourself when you read it later).

Defining "overloaded" functions in python

I really like the syntax of the "magic methods" or whatever they are called in Python, like
class foo:
def __add__(self,other): #It can be called like c = a + b
pass
The call
c = a + b
is then translated to
a.__add__(b)
Is it possible to mimic such behaviour for "non-magic" functions? In numerical computations I need the Kronecker product, and am eager to have "kron" function such that
kron(a,b)
is in fact
a.kron(b)?
The use case is: I have two similar classes, say, matrix and vector, both having Kronecker product. I would like to call them
a = matrix()
b = matrix()
c = kron(a,b)
a = vector()
b = vector()
c = kron(a,b)
matrix and vector classes are defined in one .py file, thus share the common namespace. So, what is the best (Pythonic?) way to implement functions like above? Possible solutions:
1) Have one kron() functions and do type check
2) Have different namespaces
3) ?
The python default operator methods (__add__ and such) are hard-wired; python will look for them because the operator implementations look for them.
However, there is nothing stopping you from defining a kron function that does the same thing; look for __kron__ or __rkron__ on the objects passed to it:
def kron(a, b):
if hasattr(a, '__kron__'):
return a.__kron__(b)
if hasattr(b, '__rkron__'):
return b.__rkron__(a)
# Default kron implementation here
return complex_operation_on_a_and_b(a, b)
What you're describing is multiple dispatch or multimethods. Magic methods is one way to implement them, but it's actually more usual to have an object that you can register type-specific implementations on.
For example, http://pypi.python.org/pypi/multimethod/ will let you write
#multimethod(matrix, matrix)
def kron(lhs, rhs):
pass
#multimethod(vector, vector)
def kron(lhs, rhs):
pass
It's quite easy to write a multimethod decorator yourself; the BDFL describes a typical implementation in an article. The idea is that the multimethod decorator associates the type signature and method with the method name in a registry, and replaces the method with a generated method that performs type lookup to find the best match.
Technically speaking, implementing something similar to the "standard" operator (and operator-like - think len() etc) behaviour is not difficult:
def kron(a, b):
if hasattr(a, '__kron__'):
return a.__kron__(b)
elif hasattr(b, '__kron__'):
return b.__kron__(a)
else:
raise TypeError("your error message here")
Now you just have to add a __kron__(self, other) method on the relevant types (assuming you have control over these types or they don't use slots or whatever else that would prevent adding methods outside the class statement's body).
Now I'd not use a __magic__ naming scheme as in my above snippet since this is supposed to be reserved for the language itself.
Another solution would be to maintain a type:specifici function mapping and have the "generic" kron function looking up the mapping, ie:
# kron.py
from somewhere import Matrix, Vector
def matrix_kron(a, b):
# code here
def vector_kron(a, b):
# code here
KRON_IMPLEMENTATIONS = dict(
Matrix=matrix_kron,
Vector=vector_kron,
)
def kron(a, b):
for typ in (type(a), type(b)):
implementation = KRON_IMPLEMENTATION.get(typ, None)
if implementation:
return implementation(a, b)
else:
raise TypeError("your message here")
This solution doesn't work well with inheritance but it "less surprinsing" - doesn't require monkeypatching nor __magic__ name etc.
I think having one single function that delegate the actual computation is a nice way to do it. If the Kronecker product only works on two similar classes, you can even do the type checking in the function :
def kron(a, b):
if type(a) != type(b):
raise TypeError('expected two instances of the same class, got %s and %s'%(type(a), type(b)))
return a._kron_(b)
Then, you just need to define a _kron_ method on the class. This is only some basic example, you might want to improve it to handle more gracefully the cases where a class doesn't have the _kron_ method, or to handle subclasses.
Binary operations in the standart libary usually have a reverse dual (__add__ and __radd__), but since your operator only work for same type objects, it isn't useful here.

Categories

Resources