This question already has answers here:
Are there any benefits from using a #staticmethod?
(4 answers)
Closed 7 years ago.
I have a simple question : why using the staticmethod decorator on static methods ? You can make static methods that don't have the "self" parameter, without this decorator.
When using python2, it was necessary :
>>> class A:
... def p(object_to_print):
... print(object_to_print)
...
>>> A.p('test')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method p() must be called with A instance as first argument (got str instance instead)
However, if I do the exact same thing using python 3, it will works fine.
Why using a decorator if it works fine without it ? If the first parameter is not named self, it is quite obvious it is a static method. The only reason I can see is to get clearer error in cases of misuseā¦
Is there any reason for this behaviour in python 3 ?
Thanks :)
palkeo.
Try to call this method with an instance of A and you'll get an exception:
>>> a = A()
>>> a.p('test')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: p() takes 1 positional argument but 2 were given
Because the argument is considered as the instance itself:
>>> a.p()
<__main__.A object at 0x7f9f60f56048>
However, if the method is decorated with staticmethod, it works as expected:
>>> A.p('test')
test
>>> a.p('test')
test
Related
I am a python beginner and was reading about dunder methods. Is it somehow possible to change the dunder methods of classes like int or str?
For instance, can I somehow change dunder method __add__ of int class to perform multiplication instead of addition? So if I type 3 + 4, output is 12?
You can subclass, but it's worth pointing out this is likely a bad idea since no-one reasonably expects add to perform multiplication:
class FunkyInt(int):
def __add__(self, other):
return FunkyInt(self * other)
f = FunkyInt(3)
print(f + 4)
# 12
My best guess would be that you can't (which is in line with this answer). I tried a couple of options and got the same error with in-built classes. As per Chris_Rands' answer, you can always create a Class inheriting from the in-built object in question.
>>> int.__add__ = int.__mul__
int.__add__ = int.__mul__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'int'
and
>>> dict.__add__ = list.__add__
dict.__add__ = list.__add__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'dict'
Looks like the error is not a syntax problem but more explicitly you can't redefine built-in methods.
This question already has answers here:
What does it mean when the parentheses are omitted from a function or method call?
(6 answers)
Closed 2 years ago.
I've realized that some methods should be called with (), while others can't. How can I check, using IPython e.g., whether to use parentheses or not? For example the following file scratch.py
import numpy as np
arr = np.random.randn(5)
print arr.sort, "\n"
print arr.sort(), "\n";
print arr.shape, "\n";
print arr.shape(), "\n";
produces this output:
<built-in method sort of numpy.ndarray object at 0x7fb4b5312300>
None
(5,)
Traceback (most recent call last):
File "scratch.py", line 8, in <module>
print arr.shape(), "\n";
TypeError: 'tuple' object is not callable
Those are not methods, those are properties. The descriptor is invoked behind the scenes by Python itself.
Methods in Python are always invoked with a ().
Best way to check if something is a method is to read the documentation of the library.
As far as I'm aware, every builtin object in Python has a docstring. Except, as I just found out today, None. Why is this?
None has no other function than to exist. It is one instance, not a type, while other built-ins are invariably callable or are instances of something that is.
Strings, numbers, booleans, etc. all have a callable type object, that often has specific conversion functionality as well (bool(), int(), str()). None doesn't; it's type doesn't produce anything because there is just the one instance:
>>> type(None)
<type 'NoneType'>
>>> type(None)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'NoneType' instances
None is not the only such object. Ellipsis and NotImplemented are other such objects:
>>> Ellipsis.__doc__ is None
True
>>> NotImplemented.__doc__ is None
True
>>> type(Ellipsis)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'ellipsis' instances
>>> type(NotImplemented)()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'NotImplementedType' instances
They are all sentinels, objects that signal a specific state or value, but are not useful outside of that function.
As such, they may have meaning in how they are used, not how they are created. The correct place to document this is the Datamodel reference documentation, not in docstrings.
This question already has an answer here:
Python: subscript a module
(1 answer)
Closed 7 years ago.
So it's quite a simple question. how do I add __getitem__ to a Python module. I mostly just want it as an ease of use, however it's confusing why it wouldn't let me 'just set it'. Below is a simple example of __getitem__ semi-working, however I wish for the other['test'] to work.
Here's the full output:
hello
hello
Traceback (most recent call last):
File "main.py", line 4, in <module>
print other['test']
TypeError: 'module' object has no attribute '__getitem__'
main.py
import other
print other.get('test')
print other.__getitem__('test')
print other['test']
other.py
test = 'hello'
def __getitem__(name):
return globals()[name]
get = __getitem__
I've tried to set __getitem__ using globals() aswell, globals()['__getitem__'] = __getitem__. It didn't work. And I tried to set it in main.py. So I'm confused as to why it's so adamant in not allowing me to use other['test'].
If it's impossible, then a short reason would be good.
Special methods are looked up on the type, not on an instance. Python looks for type(other).__getitem__() and that isn't available. You'd have to add the __getitem__ method to the module type; you can't in Python.
You'd have to replace the whole module instance in sys.modules with an instance of your own class to achieve what you want:
class MyModule(object):
def __init__(self, namespace):
self.__dict__.update(namespace)
def __getitem__(name):
return self.__dict__[name]
import other
import sys
sys.modules[other.__name__] = MyModule(other.__dict__)
This limitation doesn't just apply for modules, it applies for anything such that the type is not object or some subclass of object, or something with a metaclass that never bottoms out with object in the mro.
For example, you can also see this happening with type type:
In [32]: class Foo(type):
....: pass
....:
In [33]: type(Foo)
Out[33]: type
In [34]: Foo.__getitem__ = lambda x, y: x.__dict__.get(y)
In [35]: Foo.foo = "hello"
In [36]: Foo['foo']
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-38-e354ca231ddc> in <module>()
----> 1 Foo['foo']
TypeError: 'type' object has no attribute '__getitem__'
In [37]: Foo.__dict__.get('foo')
Out[37]: 'hello'
The reason is that at the C-API level, both module and type are particular instances of PyTypeObject which don't implement the required protocol for inducing the same search mechanism that the PyTypeObject implementation of object and friends does implement.
To change this aspect of the language itself, rather than hacking a replacement of sys.modules, you would need to change the C source definitions for PyModule_Type and PyType_Type such that there were C functions created for __getitem__ and added to the appropriate location in the C-API big PyTypeObject struct-o-magic-functions (a lot of which is expanded by the macro PyObject_HEAD) instead of 0 (which is the sentinel for does not exist), and recompile Python itself with these modified implementations of module and type.
I'm writing a class which extends pySerial's serial.Serial class, and I'm having trouble using the readline() function.
I'm able to reproduce the problem with as little code as this:
import serial
class A(serial.Serial):
def read(self):
return super(A, self).readline()
a = A()
a.read()
When I run this code, I get a traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in read
TypeError: read() takes exactly 1 argument (2 given)
I know I'm missing something here. I would expect it to pass just one argument (self). Where does the second argument come from?
Also, I tried using inspect.getcallargs(a.read) to figure out that second argument, but I then got this traceback:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/inspect.py", line 900, in getcallargs
args, varargs, varkw, defaults = getargspec(func)
File "/usr/lib/python2.7/inspect.py", line 815, in getargspec
raise TypeError('{!r} is not a Python function'.format(func))
TypeError: <built-in method readline of A object at 0xecf3d0> is not a Python function
This makes some sense, assuming PySerial's readline() is a native C function or system call. Am I correct in assuming this is why this happens?
Serial.read() accepts an optional argument, size, whose default value is 1. Presumably Serial.readline() calls the read() method using this argument. You've overridden read(), but you haven't given your version the size argument, so you get an error when readline() calls your version of read().
When you fix the error, you'll probably have a problem with recursion; I suspect the read() method should not call readline().