Supposed that you have a python class (say B) that is a derived class of some other class (say A) and that class A has both class variables and #classmethods that help you change or view these class variables. I had assumed that a #classmethod in class A that sets a class A class variable using the syntax cls.variable_name = value would work.
This seems to work sometimes but not always which confuses me. Below is an example that does not set the class variables as I would expect. Therefore I cannot tell what cls.something will be accessing and so I have to use A.something which seems that I will be missing the capabilities of cls.something in #classmethods. What does cls.something actually access in class methods and why does the following example not set the test class class variables?
The following example with output hopefully demonstrates what I mean:
class Test():
epf = 'A'
#classmethod
def set_formats(cls, p):
cls.epf = p
#classmethod
def form(cls):
return cls.epf
class Mytest(Test):
pass
Here is the output:
>>>c=Mytest
>>>Test.form()
'A'
>>>c.set_formats(p='a')
>>>Test.epf
'A'
>>>c.form()
'a'
>>>c.epf
'a'
So in this example the classmethods are not changing the class variable as I would expect and instead an instance variable seems to appear. If I do the above without a derived class then it works as expected. Hmm? Clearly missing something here!
Now if I change the c.set_formats(p='a', f='A') to Test.set_formats(p='a', f='A') it does work. Is it because c.set_formats uses the class method with cls being an instance?
Edit: Made the code much smaller and changed conventions as requested.
Is it because c.set_formats uses the class method with cls being an instance?
Yes, you can check via print calls showing the ids of the involved objects.
Related
I'm wondering if there is a way to make the referencing of static variables more convenient in a base class by defining some type of static reference to the derived class type?
Note: code edited after posting
class base:
MainType = None
StaticVariables = xyz
def Func(self):
base.MainType.StaticVariables = 0
class derived(base):
base.MainType = THISCLASS # pseudo code - no idea how to do this
I hope this isn't too confusing. I've read that you need to use type(self).StaticVariables to access any static variables, so I was hoping there may be some way to record the derived class type ahead of time to make them more accessible. Is something like this possible? Or is it a bad idea? I'm also curious to know if its possible to access the type of a class that is being defined. Is there any equivalent to 'self' for types (rather than instances) while outside of functions?
Edit: Have yet another question in case anyone is browsing by and sees this. When a base class defines a static variable, does this static variable get duplicated for each derived type, or does only one version of it exist regardless of the number of derived types?
If I understand you correctly, this is what classmethod is for:
class Base():
name = 'base'
#classmethod
def say_hi(cls):
print(f'Hi from {cls.name}!')
class Derived(Base):
name = 'derived'
Base().say_hi()
Derived().say_hi()
Output:
Hi from base!
Hi from derived!
Instead of taking a reference to the current instance, in the form of self, classmethods take a reference to the type of the current instance, through some nice decorator magic. This lets you call them like normal methods without having to scatter type(self) all over the place.
Pretty much what the title says but I will put some example code to clarify.
I would like to know why I can assign Repair, a reference to the class, to an instance variable but not to a class variable
class NotWorkingDefinitions:
# This will give unresolved reference
a = Repair
class WorkingDefitinions:
def __init__(self):
# This is fine
self.a = Repair
class Repair():
def __init__(self):
whatever = 10
def dosmt(self):
print("staring at a wall")
EDIT: The full answer is given over the different comments. It wasn't about not being able to assign to a class variable. It is just that class variables are immediately resolved and instance variables are not. The latter makes that defining Repair() class after WorkingDefinitions is not an issue.
The above code works if you move Repair to the top. The content of a class is evaluated from top to bottom, so any referenced classes must be defined before actually referencing them.
An example that explores this a bit more in terms of runtime and load-time could be:
# this will not work because the B class is referenced before definition
class A(object):
b_class = B
class B(object):
pass
Alternatively,
# this will work because B is defined first and used later
class B(object):
pass
class A(object):
b_class = B
But both of the examples above do not have a runtime-specific behavior. If instead you wanted A to use B and you had a really good reason to define A first, then you could get away with
class A(object):
def __init__(self):
# bind the B class to each instance of A
self.b_class = B
class B(object):
pass
a = A()
a.b_class
> __main__.B
But the short answer is you must define a variable before using it and when you bind a variable directly to a class (in the class definition, not a method) it must be defined.
The full answer is given over the different comments. It is not about not being able to assign to a class variable. It is that class variables are immediately evaluated and instance variables are not. Instance variables will be evaluated during initiation. The latter makes that defining Repair() class after WorkingDefinitions is not an issue.
I want to set attributes dynamically to a FlaskForm like this
form = ModelForm(request.form)
file form.py
class ModelForm(FlaskForm):
def __init__(self, postData):
super(ModelForm, self).__init__()
for p in postData:
setattr(ModelForm, p, StringField(p, validators=[InputRequired()]))
But it only work for the second time running, the first time running, it doesn't work.
I really don't understand how python constructor works.
As this post, it said because
class A is not fully initialized when you do your setattr(A, p, v)
there.
But in other languages, the object have to be created after constructor finished, and it has full class variables, properties declared in the constructor ?
For example, it works and can print a.key. So what's difference there in the flask constructor and this?
class A(object):
def __init__(self):
self.a = 'i am a accessor'
setattr(self, 'key', 'value')
a = A()
print a.a
print a.key
class A is not fully initialized
means, when you create your first instance of your class with form=ModelForm(), you start adding attributes to the class you are currently instancing from. I don't know, how exactly this works internally in Python. But since you say this only works in the second run, I guess the object is first created with all attributes defined for the class, then __init__ is executed. So the new attributes are added to late.
In other words: Your are trying to change the class definition after you already created an instance of it. You need to add all your attributes, before you instantiate.
Now what you need to do is: first define the class without any dynamic fields. Then, after the class definition, you add the loop with your dynamic fields.
ModelForm = FlaskForm
for p in postData:
setattr(ModelForm, p, StringField(p, validators=[InputRequired()]))
Or if you need to add some other stuff in class definition:
class ModelForm(FlaskForm):
def foo(self):
return 'bar'
for p in postData:
setattr(ModelForm, p, StringField(p, validators=[InputRequired()]))
And then, somewhere in your view function, you can use form = ModelForm(request.form) as usual.
Usually you know what fields you need beforehand. The form just answers on what it got from the GET request. So this should be fine.
But maybe you added some more fields with some JS on client side, which the server does not know about (yet). In that case you might try to put the class definition into the local scope of the view function which handles the POST request.
For a recursive function we can do:
def f(i):
if i<0: return
print i
f(i-1)
f(10)
However is there a way to do the following thing?
class A:
# do something
some_func(A)
# ...
If I understand your question correctly, you should be able to reference class A within class A by putting the type annotation in quotes. This is called forward reference.
class A:
# do something
def some_func(self, a: 'A')
# ...
See ref below
https://github.com/python/mypy/issues/3661
https://www.youtube.com/watch?v=AJsrxBkV3kc
In Python you cannot reference the class in the class body, although in languages like Ruby you can do it.
In Python instead you can use a class decorator but that will be called once the class has initialized. Another way could be to use metaclass but it depends on what you are trying to achieve.
You can't with the specific syntax you're describing due to the time at which they are evaluated. The reason the example function given works is that the call to f(i-1) within the function body is because the name resolution of f is not performed until the function is actually called. At this point f exists within the scope of execution since the function has already been evaluated. In the case of the class example, the reference to the class name is looked up during while the class definition is still being evaluated. As such, it does not yet exist in the local scope.
Alternatively, the desired behavior can be accomplished using a metaclass like such:
class MetaA(type):
def __init__(cls):
some_func(cls)
class A(object):
__metaclass__=MetaA
# do something
# ...
Using this approach you can perform arbitrary operations on the class object at the time that the class is evaluated.
Maybe you could try calling __class__.
Right now I'm writing a code that calls a class method from within the same class.
It is working well so far.
I'm creating the class methods using something like:
#classmethod
def my_class_method(cls):
return None
And calling then by using:
x = __class__.my_class_method()
It seems most of the answers here are outdated. From python3.7:
from __future__ import annotations
Example:
$ cat rec.py
from __future__ import annotations
class MyList:
def __init__(self,e):
self.data = [e]
def add(self, e):
self.data.append(e)
return self
def score(self, other:MyList):
return len([e
for e in self.data
if e in other.data])
print(MyList(8).add(3).add(4).score(MyList(4).add(9).add(3)))
$ python3.7 rec.py
2
Nope. It works in a function because the function contents are executed at call-time. But the class contents are executed at define-time, at which point the class doesn't exist yet.
It's not normally a problem because you can hack further members into the class after defining it, so you can split up a class definition into multiple parts:
class A(object):
spam= 1
some_func(A)
A.eggs= 2
def _A_scramble(self):
self.spam=self.eggs= 0
A.scramble= _A_scramble
It is, however, pretty unusual to want to call a function on the class in the middle of its own definition. It's not clear what you're trying to do, but chances are you'd be better off with decorators (or the relatively new class decorators).
There isn't a way to do that within the class scope, not unless A was defined to be something else first (and then some_func(A) will do something entirely different from what you expect)
Unless you're doing some sort of stack inspection to add bits to the class, it seems odd why you'd want to do that. Why not just:
class A:
# do something
pass
some_func(A)
That is, run some_func on A after it's been made. Alternately, you could use a class decorator (syntax for it was added in 2.6) or metaclass if you wanted to modify class A somehow. Could you clarify your use case?
If you want to do just a little hacky thing do
class A(object):
...
some_func(A)
If you want to do something more sophisticated you can use a metaclass. A metaclass is responsible for manipulating the class object before it gets fully created. A template would be:
class AType(type):
def __new__(meta, name, bases, dct):
cls = super(AType, meta).__new__(meta, name, bases, dct)
some_func(cls)
return cls
class A(object):
__metaclass__ = AType
...
type is the default metaclass. Instances of metaclasses are classes so __new__ returns a modified instance of (in this case) A.
For more on metaclasses, see http://docs.python.org/reference/datamodel.html#customizing-class-creation.
If the goal is to call a function some_func with the class as an argument, one answer is to declare some_func as a class decorator. Note that the class decorator is called after the class is initialized. It will be passed the class that is being decorated as an argument.
def some_func(cls):
# Do something
print(f"The answer is {cls.x}")
return cls # Don't forget to return the class
#some_func
class A:
x = 1
If you want to pass additional arguments to some_func you have to return a function from the decorator:
def some_other_func(prefix, suffix):
def inner(cls):
print(f"{prefix} {cls.__name__} {suffix}")
return cls
return inner
#some_other_func("Hello", " and goodbye!")
class B:
x = 2
Class decorators can be composed, which results in them being called in the reverse order they are declared:
#some_func
#some_other_func("Hello", "and goodbye!")
class C:
x = 42
The result of which is:
# Hello C and goodbye!
# The answer is 42
What do you want to achieve? It's possible to access a class to tweak its definition using a metaclass, but it's not recommended.
Your code sample can be written simply as:
class A(object):
pass
some_func(A)
If you want to refer to the same object, just use 'self':
class A:
def some_func(self):
another_func(self)
If you want to create a new object of the same class, just do it:
class A:
def some_func(self):
foo = A()
If you want to have access to the metaclass class object (most likely not what you want), again, just do it:
class A:
def some_func(self):
another_func(A) # note that it reads A, not A()
Do remember that in Python, type hinting is just for auto-code completion therefore it helps IDE to infer types and warn user before runtime. In runtime, type hints almost never used(except in some cases) so you can do something like this:
from typing import Any, Optional, NewType
LinkListType = NewType("LinkList", object)
class LinkList:
value: Any
_next: LinkListType
def set_next(self, ll: LinkListType):
self._next = ll
if __name__ == '__main__':
r = LinkList()
r.value = 1
r.set_next(ll=LinkList())
print(r.value)
And as you can see IDE successfully infers it's type as LinkList:
Note: Since the next can be None, hinting this in the type would be better, I just didn't want to confuse OP.
class LinkList:
value: Any
next: Optional[LinkListType]
It's ok to reference the name of the class inside its body (like inside method definitions) if it's actually in scope... Which it will be if it's defined at top level. (In other cases probably not, due to Python scoping quirks!).
For on illustration of the scoping gotcha, try to instantiate Foo:
class Foo(object):
class Bar(object):
def __init__(self):
self.baz = Bar.baz
baz = 15
def __init__(self):
self.bar = Foo.Bar()
(It's going to complain about the global name 'Bar' not being defined.)
Also, something tells me you may want to look into class methods: docs on the classmethod function (to be used as a decorator), a relevant SO question. Edit: Ok, so this suggestion may not be appropriate at all... It's just that the first thing I thought about when reading your question was stuff like alternative constructors etc. If something simpler suits your needs, steer clear of #classmethod weirdness. :-)
Most code in the class will be inside method definitions, in which case you can simply use the name A.
When I write class in python, most of the time, I am eager to set variables I use, as properties of the object. Is there any rule or general guidelines about which variables should be used as class/instance attribute and which should not?
for example:
class simple(object):
def __init(self):
a=2
b=3
return a*b
class simple(object):
def __init(self):
self.a=2
self.b=3
return a*b
While I completely understand the attributes should be a property of the object. This is simple to understand when the class declaration is simple but as the program goes longer and longer and there are many places where the data exchange between various modules should be done, I get confused on where I should use a/b or self.a/self.b. Is there any guidelines for this?
Where you use self.a you are creating a property, so this can be accessed from outside the class and persists beyond that function. These should be used for storing data about the object.
Where you use a it is a local variable, and only lasts while in the scope of that function, so should be used where you are only using it within the function (as in this case).
Note that __init is misleading, as it looks like __init__ - but isn't the constructor. If you intended them to be the constructor, then it makes no sense to return a value (as the new object is what is returned).
class Person(object):
def __init__(self, name):
# Introduce all instance variables on __init__
self.name = name
self.another = None
def get_name(self):
# get_name has access to the `instance` variable 'name'
return self.name
So if you want a variable to be available on more than one method, make
it an instance variable.
Notice my comment on introducing all instance vars on __init__.
Although the example below is valid python don't do it.
class Person(object):
def __init__(self):
self.a = 0
def foo(self):
self.b = 1 # Whoa, introduced new instance variable
Instead initialize all your instance variables on __init__ and set
them to None if no other value is appropriate for them.
I try to imagine what I want the API of my class to look like prior to implementing it. I think to myself, If I didn't write this class, would I want to read the documentation about what this particular variable does? If reading that documentation would simply waste my time, then it should probably be a local variable.
Occasionally, you need to preserve some information, but you wouldn't necessarily want that to be part of the API, which is when you use the convention of appending an underscore. e.g. self._some_data_that_is_not_part_of_the_api.
The self parameter refers to the object itself. So if you need to use on of the class attributes outside of the class you would it call it as the name of class instance and the attribute name. I don't think there is any guideline on when to use self, it all depends on your need. When you are building a class you should try to think about what you will use the variables you creating for. If you know for sure that you will need that specific attribute in the program you are importing your class, then add self.