How to call static methods in functions? Scope of static methods - python

Suppose I create a class with a static method and want to run that method from another classes method or script function.
What is the scope of the static method?
ex:
def Class myClass:
#staticmethod
def mystaticmethod(input):
print("blah")
def scriptfunc():
myClass.mystaticmethod()
Is this valid?

What you have is valid.
But too elaborate on the purpose of #staticmethod, here's Short answer:
Declaring a #staticmethod would mean 2 things:
You don't care about the properties or attributes of a method as it's independent of other classes,
You do not require creating an __init__ or a super method to override it's content or attributes, and doesn't require a subclass/parent class to handle itself.

You can just do ClassName.methodName(), from anywhere where ClassName is accessible (so, in the same enclosing scope, or in another module after having imported ClassName.
Python has docs on namespace precedences, which you can read here. Suffice it to say; for objects in general, their 'private' namespace is entirely accessible via the dot operator, as long as the object itself is accessible. This includes all variables and functions defined directly within.

Related

How python resolves private(double underscore) methods inside a class?

Consider the following class
class Foo(object):
#staticmethod
def __is():
print('__is')
def m(self):
Foo.__is() # executes
Foo.__is() # fails because of mangling
print(Foo.__dict__.keys())
Foo.__is() when it is run after the class is defined, it fails because of name mangaling. How is python interpreter able to resolve Foo.__is() inside methods but not outside the class?
Name mangling for names starting with __ inside a class, is implemented by rewriting this names to the mangled form, inside the class ONLY. So your Foo.__is inside the class gets replaced by _Foo__is that is now present in the class __dict__. That attribute is accessible either inside or outside the class, so no private protection. But after replacement the __is name does not exist anywhere (I think), that's why it does not work from outside.
From the Python help:
"__*"
Class-private names. Names in this category, when used within the
context of a class definition, are re-written to use a mangled form
to help avoid name clashes between “private” attributes of base and
derived classes. See section Identifiers (Names).
Also see my comment to errors in your code snippet.
You can think of classes as of namespaces with some whistles.
One of whistles is ability to resolve __methods inside themselves without _class__method. This is no different from "magic" of automatically passing instances as first argument to methods (your regular self)
To illustrate "namespace" idea, you can do some weird things like
class A:
def insane():
return 42
for _ in range(5):
print(insane()

Why must instance variables be defined inside of methods?

Why must instance variables be defined inside of methods? In other words why must self only be used to define new variables inside of methods in a class. Why can't you define variables using self as part of the class, but outside of methods.
"Instance variables are those variables for which each class object has it's own copy of it" - this definition doesn't say anything about methods. So, given that the definition doesn't mention methods why can't I define an instance variable (in other words use self to define a new variable) inside of a class, but outside of a method?
Python requires the object reference (implicit or explicit this in Java, for example) to be explicit. Inside methods -- bound functions -- the first param in the function definition is the instance. (This is conventionally called self but you can use any name.)
If you define
class C:
x = 1
there is no self reference, unlike, e.g. Java, where this is implicit.
Because the mechanism which Python uses to deal with OOP are very simple. There's no special syntax to define classes really, the class keyword is a very thin layer over what amounts to creating a dict. Everything you define inside a class Foo: block basically ends up as the contents of Foo.__dict__. So there's no syntax to define attributes of the instance resulting from calling Foo(). You add instance attributes simply by attaching them to the object you get from calling Foo(), which is self in __init__ or other instance methods.
For that to answer you need to know a little bit how the Python interpreter works.
In general every class and method definition are separate objects.
What you do when calling a method is that you pass the class instance as first parameter to the method. With that the method knows on what instance it is running on (and therefore where to allocate instance variables to).
This however only counts for instance methods.
Of course you can also create classmethods with #classmethod these take the class type as argument instead of an instance and can therefore not be used to create variables on the self context.
Why must instance variables be defined inside of methods?
They don't. You can define them from anywhere, as long as you have an instance (of a mutable type):
class Foo(object):
pass
f = Foo()
f.bar = 42
print(f.bar)
In other words why must self only be used to define new variables inside of methods in a class. Why can't you define variables using self as part of the class, but outside of methods.
self (which is only a naming convention, there's absolutely nothing magical here) is used to represent the current instance. How could you use it at the class block's top-level where you don't have any instance at all (and not even the class itself FWIW) ?
Defining the class "members" at the class top-level is mostly a static languages thing, where "objects" are mainly (technically) structs (C style structs, or Pascal style records if you prefer) with a statically defined memory structure.
Python is a dynamic language, which instead uses dicts as supporting data structure, so someobj.attribute is usually (minus computed attributes etc) resolved as someobj.__dict__["attribute"] (and someobj.attribute = value as someobj.__dict__["attribute"] = value).
So 1/ it doesn't NEED to have a fixed, explicitely defined data structure, and 2/ yet it DOES need to have an instance at end to set an attribute on it.
Note that you can force a class to use a fixed memory structure (instead of a plain dict) using slots, but you will still need to set the values from within a method (canonically the __init__, which exists for this very reason: initializing the instance's attributes).

What is more pythonic for a staticmethod? `self` or the class itself?

Let's say I have a class (in python3.6)
class Testing:
def __init__(self, stuff):
self.stuff = stuff
#staticmethod
def method_one(number):
"""My staticmethod"""
return number + 1
def method_two(self):
"""Other method"""
number = 10
# option A
self.method_one(number)
# option B
Testing.method_one(number)
What is more python here?
option A, using the self var
option B, using the class itself
I tend to think A, but I am unsure and couldn't find a solid answer on the topic
In the case of static methods I would always prefer notation B over notation A. The main reason for this is that notation B tells me something about the method that I wouldn't have known if you used notation A.
If you use the class name instead of self it is immediately obvious to the reader that they are dealing with a static method. This way the reader knows that the method doesn't use or change the class or instance state. If you use self you have to check the actual method to see if the class or instance state is used.
In fact using self is not good in static methods. so when you want to call static methods you can use option B , with class object.
So for calling other methods means non static here is the strategy :
If both methods are in same class you can use self like you mentioned in option A.
option B(which means calling a methodinside a class... using class object) , you can use when function that you want to call is in another class
UPDATE :
For calling static methods in the same class you can use two ways,other than self. They are more pythonic.
1. call from class : classname.static_method_name()
2. call from instances
these two ways are more pythonic than self. So in your case option B is more pythonic.
For me Option B has the disadvantage that is explicitly uses the class name Testing again. If the class is renamed (or contents are copy/pasted), this needs to be updated. Using
type(self).method_one(number)
seems a way if one really wants to highlight that this is not an instance method.
Note that this gives you your own class. If your class overwrites a static method of the parent class with and instance method that has the name name, then the call fill fail. Using super().some_static_method() will work, but since super() returns a proxy object type(super()).some_static_method() does not work.
So practically, using self seems ok if all you care about is accessing your (currently set) method. A class instance also "inherits" the class-methods and static methods of parents.
But if you really want to invoke the static method from Testing regardless of what instance you are currently in, then use Testing.method_one(). It's a bit hard to argue about the most "pythonic way" when the whole class/inheritance design can be questioned also...

Discovering dependency API in a python class

In the following class:
class SomeClass(object):
def __init__(self, somedependency):
self._somedependency = somedependency
def do_something(self):
self._field = _somedependency.get_something()
Is it possible to "know" that somedependency has a function called get_something() at runtime just as you would know the public methods and properties of a constructor parameter in C# at compile time?
EDIT: I'd like to get the somedependency's members and create a new type with those members, so what I need to perform an action such as "I'm calling methods and properties of this constructor parameter in the calling class. Give me all those methods and parameters as these are seen in the calling class". As I don't know the type of the constructor parameter I cannot determine this in a way you can do in static languages.
If you just want to verify that a known method exists, use func = getattr(_somedependency, 'get_something'); if func: func().
If you want more inspection like what methods a class or instance has, check out the built in inspect module.

Python: functions in a class and memory

If I have a class with several functions:
class Example:
def func1(self):
print 'Hi1'
def func2(self):
print 'Hi2'
def func3(self):
print 'Hi3'
If I create several instances of 'Example', does each instance store its own copies of the functions in the class? Or does Python have a smart way to store the definition only once and look it up every time an instance uses a function in the class?
Also, what about static functions? Does the class keep only one copy of each static function?
When instantiating a class, no new function objects are created, neither for instance methods nor for static methods. When accessing an instance method via obj.func1, a new wrapper object called a "bound method" is created, which will be only kept as long as needed. The wrapper object is ligh-weight and contains basically a pointer to the underlying function object and the instance (which is passed as self parameter when then function is called).
Note that using staticmethod is almost always a mistake in Python. It owes its existence to a historical mistake. You usually want a module-level function if you think you need a static method.
The functions are "stored" in the class, both static and non-static.

Categories