Is `list()` considered a function? - python

list is obviously a built-in type in Python. I saw a comment under this question which calls list() a built-in function. And when we check the documentation, it is, indeed, included in Built-in functions list but the documentation again states:
Rather than being a function, list is actually a mutable sequence type
Which brings me to my question: Is list() considered a function? Can we refer to it as a built-in function?
If we were talking about C++, I'd say we are just calling the constructor, but I am not sure if the term constructor applies to Python (never encountered its use in this context).

list is a type, which means it is defined somewhere as a class, just like int and float.
>> type(list)
<class 'type'>
If you check its definition in builtins.py (the actual code is implemented in C):
class list(object):
"""
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
"""
...
def __init__(self, seq=()): # known special case of list.__init__
"""
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
# (copied from class doc)
"""
pass
So, list() is not a function. It is just calling list.__init__() (with some arguments which are irrelevant for this discussion) just like any call to CustomClass() is doing.
Thanks for #jpg for adding in the comments: classes and functions in Python have a common property: they are both considered as callables, which means they are allowed to be invoked with (). There is a built-in function callable that checks if the given argument is callable:
>> callable(1)
False
>> callable(int)
True
>> callable(list)
True
>> callable(callable)
True
callable is also defined in builtins.py:
def callable(i_e_, some_kind_of_function): # real signature unknown; restored from __doc__
"""
Return whether the object is callable (i.e., some kind of function).
Note that classes are callable, as are instances of classes with a
__call__() method.
"""
pass

When you call list(), you're invoking the constructor of the list class (list.__init__).
If you have any doubt about the use of the term "constructor" in Python, this is the exact word that the implementers of list chose to refer to __init__:
https://github.com/python/cpython/blob/master/Objects/listobject.c#L2695

Related

Strange behavior assigning builtin methods as class attributes

I encountered a strange behavior that I cannot explain when assigning builtin methods as attributes to a class in Python.
If I run the following python file:
class A:
a = bin
b = lambda x: bin(x)
print(A().a(2))
print(A().b(2))
The call to A().a(2) returns a byte string, but the call to A().b(2) raises:
TypeError: <lambda>() takes 1 positional argument but 2 were given
The signature of the builtin function bin is supposedly bin(number, /), which seems identical to the signature provided by the lambda above. However, it appears as if A().a is treated as a static method, whereas A().b is treated like an "instance" method (with a self argument implicitly added to the provided lambda). There is an explanation of a similar issue here (calling a function saved in a class attribute: different behavior with built-in function vs. normal function), which claims that the reason these two are treated differently is because one is a builtin_function_or_method and the other is a function type.
However, there is inconsistent behavior even within builtins.
class B(int):
c = pow
d = round
print(B(1).d(2))
print(B(1).c(2))
In the case of pow and round, round is treated like an instance method while pow is treated as a static method. Both of these builtins are callables capable of taking two unnamed arguments.
This behavior exists across all the versions of Python 2.* and 3.* I've tried.
The answer you've referenced is correct.
In the counter-example you gave the two built-in functions are indeed treated the same, that is no bound method object is created:
B(1).d(2) == round(2) # not round(B(1), 2)
B(1).c(2) == pow(2) # not pow(B(1), 2)
the issue arises from passing only one argument to pow which takes at least 2, as opposed to round which does only need one

In python, is there some kind of mapping to return the "False value" of a type?

I am looking for some kind of a mapping function f() that does something similar to this:
f(str) = ''
f(complex) = 0j
f(list) = []
Meaning that it returns an object of type that evaluates to False when cast to bool.
Does such a function exist?
No, there is no such mapping. Not every type of object has a falsy value, and others have more than one. Since the truth value of a class can be customized with the __bool__ method, a class could theoretically have an infinite number of (different) falsy instances.
That said, most builtin types return their falsy value when their constructor is called without arguments:
>>> str()
''
>>> complex()
0j
>>> list()
[]
Nope, and in general, there may be no such value. The Python data model is pretty loose about how the truth-value of a type may be implemented:
object.__bool__(self)
Called to implement truth value testing and the built-in operation
bool(); should return False or True. When this method is not defined,
__len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__()
nor __bool__(), all its instances are considered true.
So consider:
import random
class Wacky:
def __bool__(self):
return bool(random.randint(0,1))
What should f(Wacky) return?
This is actually called an identity element, and in programming is most often seen as part of the definition of a monoid. In python, you can get it for a type using the mzero function in the PyMonad package. Haskell calls it mempty.
Not all types have such a value to begin with. Others may have many such values. The most correct way of doing this would be to create a type-to-value dict, because then you could check if a given type was in the dict at all, and you could chose which value is the correct one if there are multiple options. The drawback is of course that you would have to somehow register every type you were interested in.
Alternatively, you could write a function using some heuristics. If you were very careful about what you passed into the function, it would probably be of some limited use. For example, all the cases you show except complex are containers that generalize with cls().
complex actually works like that too, but I mention it separately because int and float do not. So if your attempt with the empty constructor fails by returning a truthy object or raising a TypeError, you can try cls(0). And so on and so forth...
Update
#juanpa.arrivillaga's answer actually suggests a clever workaround that will work for most classes. You can extend the class and forcibly create an instance that will be falsy but otherwise identical to the original class. You have to do this by extending because dunder methods like __bool__ are only ever looked up on the class, never on an instance. There are also many types where such methods can not be replaced on the instance to begin with. As #Aran-Fey's now-deleted comment points out, you can selectively call object.__new__ or t.__new__, depending on whether you are dealing with a very special case (like int) or not:
def f(t):
class tx(t):
def __bool__(self):
return False
try:
return object.__new__(tx)
except TypeError:
return tx.__new__(tx)
This will only work for 99.9% of classes you ever encounter. It is possible to create a contrived case that raises a TypeError when passed to object.__new__ as int does, and does not allow for a no-arg version of t.__new__, but I doubt you will ever find such a thing in nature. See the gist #Aran-Fey made to demonstrate this.
No such function exists because it's not possible in general. A class may have no falsy value or it may require reversing an arbitrarily complex implementation of __bool__.
What you could do by breaking everything else is to construct a new object of that class and forcibly assign its __bool__ function to one that returns False. Though I suspect that you are looking for an object that would otherwise be a valid member of the class.
In any case, this is a Very Bad Idea in classic style.

Python 3 built-in functions and classes

When I am creating a list using below statement
a = list('jane')
Am I calling Python's built-in list function or instantiating list class.
My understanding is we are instantiating list class by passing 'jane' as argument.
However, the Python's documentation https://docs.python.org/3/library/functions.html says list() is built-in function.
The docs explicitly say:
class list([iterable])
Rather than being a function, list is actually a mutable sequence type
You can easily check that:
>>> type(list)
type
if it was a function, function would be the output provided by using type.
You're instantiating a list object the same way you'd do if you created your own class and called it. type's __call__ is essentially getting invoked and sets up your instance so, though they aren't a function per se, they are callable.
The fact that they are listed in that specific section is probably for convenience, it might be confusing but reading the description of it is supposed to disambiguate this.
Your question is answered by the very documentation page you mention:
class list([iterable])
Rather than being a function, list is actually a mutable sequence type, as documented in Lists and Sequence Types — list, tuple, range.
In Python, both classes and functions are callable, so in practice, you can treat them alike.
You are instantiating a list.
class list([iterable])
Rather than being a function, list is actually a mutable sequence type, as documented in Lists and Sequence Types — list, tuple, range.

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).

What is (self) in the python code? (OOP question)

class MyController(BaseController):
def index(self):
# Return a rendered template
#return render('/test.mako')
# or, return a response
return ''
Why does the function "index" have "self"?
I got this code from Pylons controller
Many languages, like C++ and Java, have an implicit pointer inside member functions. In those languages, it is "this". Python, on the other hand, requires an EXPLICIT name to be given to that pointer. By convention, it is "self", although you could actually put anything you like in there as long as it is a valid identifier.
It's a member function (a function that's part of a class), so when it's called, the object it was called on is automatically passed as the first argument.
For example:
c = MyController()
c.index()
would call index with self equal to c. self is the standard name, but you can call it anything you want
Whenever a method in an object is called, the first parameter passed into that method is the object itself. If you do not define the first parameter as being the object you are using, you will get a TypeError exception.

Categories

Resources