What is the point of _=None in method python method signature? - python

What is the purpose of _=None in a method signature?
Example:
def method(_=None):
pass

_ is a conventional name for an unused placeholder variable in Python (and shell, and some other languages).
When not in the context of a class (that is, when defining a function rather than a method), this would define a function with a single optional (keyword) argument (defaulting to None), with a name indicating that that argument is deliberately unused (and exempting it from warnings about unused variables in some static-checking tools).
When defining a method where the first and only argument accepted is defined in this way, this becomes effectively a poor man's static method. That is to say, it's indicating that self is unused and optional, and allowing the method to be called independently of whether any object instance is associated (that is, whether a self is actually available at runtime).
Note that this is not common idiom, and using the #staticmethod decorator is going to make much more sense to readers of your code.

Related

What are the rules for adding members to Python methods safely?

I'm looking at code like this:
def foo():
return 42
foo.x = 5
This obviously adds a member to the function object named foo. I find this very useful as it makes these function objects look very similar to Objects with a __call__ function.
Are there rules I must follow to make sure I don't cause problems in future updates to Python, such as names that I must avoid? Perhaps there is a PEP or documentation section that mentions rules?
There are no rules, other than to take the reserved classes of identifiers into account. Specifically, try to avoid using dunder names:
System-defined names, informally known as “dunder” names. [...] Any use of __*__ names, in any context, that does not follow explicitly documented use, is subject to breakage without warning.
There is otherwise nothing special about functions accepting arbitrary attributes; almost anything in Python accepts arbitrary attributes if there is a place to put them (which is, almost always, a __dict__ attribute).
Within the Python standard library, function attributes are used to link decorator wrapper functions to the original wrapped function (via the functools.update_wrapper() function and it's side-kick, the #functools.wraps() decorator function), and to attach state and methods to a function when augmented by decorators (e.g. the singledispatch() decorator adds several methods and a registry to the decorated function).
It is a good technique. Rule is not shadow any dunder names which have special meanings.
Here is a good way to implement a singleton:
import faker
def my_fake_data():
if not getattr(my_fake_data, 'factory', None):
my_fake_data.factory = faker.Faker()
return my_fake_data.factory
Monkey patching uses a similar technique (setting a class attribute instead pf a function attribute) but for more "devious" reasons such as changing the implementation of a previously defined class.

Why does tf.variable_scope has a default_name argument?

The first two arguments of tf.variable_scope's __init__ method are
name_or_scope: string or VariableScope: the scope to open.
default_name: The default name to use if the name_or_scope argument is
None, this name will be uniquified. If name_or_scope is provided it
won't be used and therefore it is not required and can be None.
If I understand correctly, this argument is equivalent to (and therefore could be easily replaced with)
if name_or_scope is None:
name_or_scope = default_name
with tf.variable_scope(name_or_scope, ...):
...
Now, I am not sure I understand why it was deemed necessary to have this special treatment for the scope name — after all, many parameters could use a parameterizable default argument.
So what is the rationale behind the introduction of this argument?
You are right. It is just a convenience.
Take the case of TensorFlow models defined here. If you take a specific look at InceptionV4.py, you will see that it has a scope argument in its definition. Just below you will see that InceptionV4 has been passed as a default scope. Therefore it was entirely not required to even has a scope argument in the definition. But it makes sense, if somebody gives scope=None.
Think about it. Model definitions can get very comples very quickly. Therefore, a default_scope argument, helps in reinforcing the wisdom of the model definition writer to introduce some sort of deliberate structure in the model definition, even if the end user is very naive about it.

Why method accepts class name and name 'object' as an argument?

Consider the following code, I expected it to generate error. But it worked. mydef1(self) should only be invoked with instance of MyClass1 as an argument, but it is accepting MyClass1 as well as rather vague object as instance.
Can someone explain why mydef is accepting class name(MyClass1) and object as argument?
class MyClass1:
def mydef1(self):
return "Hello"
print(MyClass1.mydef1(MyClass1))
print(MyClass1.mydef1(object))
Output
Hello
Hello
There are several parts to the answer to your question because your question signals confusion about a few different aspects of Python.
First, type names are not special in Python. They're just another variable. You can even do something like object = 5 and cause all kinds of confusion.
Secondly, the self parameter is just that, a parameter. When you say MyClass1.mydef1 you're asking for the value of the variable with the name mydef1 inside the variable (that's a module, or class, or something else that defines the __getattr__ method) MyClass1. You get back a function that takes one argument.
If you had done this:
aVar = MyClass1()
aVar.mydef1(object)
it would've failed. When Python gets a method from an instance of a class, the instance's __getattr__ method has special magic to bind the first argument to the same object the method was retrieved from. It then returns the bound method, which now takes one less argument.
I would recommend fiddling around in the interpreter and type in your MyClass1 definition, then type in MyClass1.mydef1 and aVar = MyClass1(); aVar.mydef1 and observe the difference in the results.
If you come from a language like C++ or Java, this can all seem very confusing. But, it's actually a very regular and logical structure. Everything works the same way.
Also, as people have pointed out, names have no type associated with them. The type is associated with the object the name references. So any name can reference any kind of thing. This is also referred to as 'dynamic typing'. Python is dynamically typed in another way as well. You can actually mess around with the internal structure of something and change the type of an object as well. This is fairly deep magic, and I wouldn't suggest doing it until you know what you're doing. And even then you shouldn't do it as it will just confuse everybody else.
Python is dynamically typed, so it doesn't care what gets passed. It only cares that the single required parameter gets an argument as a value. Once inside the function, you never use self, so it doesn't matter what the argument was; you can't misuse what you don't use in the first place.
This question only arises because you are taking the uncommon action of running an instance method as an unbound method with an explicit argument, rather than invoking it on an instance of the class and letting the Python runtime system take care of passing that instance as the first argument to mydef1: MyClass().mydef1() == MyClass.mydef1(MyClass()).
Python is not a statically-typed language, so you can pass to any function any objects of any data types as long as you pass in the right number of parameters, and the self argument in a class method is no different from arguments in any other function.
There is no problem with that whatsoever - self is an object like any other and may be used in any context where object of its type/behavior would be welcome.
Python - Is it okay to pass self to an external function

Using an Abstract Base class as an argument to a function (Python)

If I have an Abstract Base Class called BaseData which has the function update which is overridden with different functionality in its Child Classes, can I have a function as follows, where I want the function to take any Child Class as an argument and call the update function for the corresponding Child Class.
def date_func(BaseData, time):
result = BaseData.update(time)
lastrow = len(result.index)
return result['Time'].iloc[lastrow],result['Time'].iloc[lastrow-100]
Sure you can. Python won't care because it doesn't do any type checking.
In fact, you can use any type that provides a compatible interface independent from whether the instance derives from BaseData.
Including the name of the ABC as the name of the parameter won't restrict it to only subclasses of the ABC. All it does is make a parameter of that name.
Any object of any type can be passed in as an argument to any function or method. Any object that - in this case - doesn't have update() will cause an AttributeError to be raised, but if the argument has an update() method that can accept the one argument given, it won't cause a problem.
If you want to be certain that the first argument is a subclass of BaseData, follow these steps:
rename the parameter to something like data. This will make it so that the name of the parameter isn't shadowing ("replacing within this context") out the actual BaseData class
write if isinstance(data, BaseData): at the beginning of the function, tabbing everything that was already there over to be within it.
(optional) write an else clause that raises an Error. If you don't do this, then None will simply be returned when the type check fails.
Now that you know how to do what you're asking, you should be aware that there are few worthwhile cases for doing this. Again, any object that fulfills the needed 'protocol' can work and doesn't need to necessarily be a subclass of your ABC.
This follows python's principle of "It's easier to ask for forgiveness than permission" (or EAFTP), which lets us assume that the person who passed in an argument gave one of a compatible type. If you're worried about the possibility of someone giving the wrong type, then you can wrap the code in a try-catch block that deals with the exception raised when it's wrong. This is how we "ask for forgiveness".
Generally, if you're going to do type checks, it's because you're prepared to handle different sets of protocols and the ABCs that define these protocols also (preferably) define __subclasshook__() so that it doesn't JUST check whether the class is 'registered' subclass, but rather follows the prescribed protocol.

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

Categories

Resources