I am a beginner with Python, in this loop i trying to use the methods of the variable "data_point"
Behind the variable "data_point" is a simple getter and setter class, nevertheless in the autocompletion of PyCharm it shows me only 2 methods instead of all.
What do I have to do to see all methods of this class?
I have added the type, but the behavior is the same
This is my model class with getter and setter
You need to annotate data_points as a list of your class
def create_a_subplot(self, ax, data_points: list[YourClass]):
...
Prior to version 3.9 you need to use typing.List
from typing import List
def create_a_subplot(self, ax, data_points: List[YourClass]):
...
Related
I'm trying to set some default class variables in a base class so all subclasses are guaranteed to have a default value. Some of these I'd like to be dynamic based upon the subclass (DISPLAY_NAME in the example below). The use of __qualname__ in _ExtensionBase doesn't work because it sets DISPLAY_NAME to the static string "_ExtensionBase".
Is there a simpler way to do this, or any issues with the way I've found below? I haven't stumbled into any, bit it feels like pushing some limits of the intended uses of property and classmethod
class _ExtensionBase:
PRIORITY: float = 1.0
VERSION_STR: str = 'n/a'
#classmethod
#property
def DISPLAY_NAME(cls) -> str:
return cls.__name__
class ConcreteSubclass(_ExtensionBase): pass
assert ConcreteSubclass.DISPLAY_NAME == "ConcreteSubclass"
Try this:
ConcreteSubclass.__name__
Per the note in Python 3.11's entry on #classmethod (link)
Changed in version 3.9: Class methods can now wrap other descriptors
such as property().
Changed in version 3.10: Class methods now inherit the method
attributes (__module__, __name__, __qualname__,
__doc__ and __annotations__) and have a new
__wrapped__ attribute.
Changed in version 3.11: Class methods can no longer wrap other
descriptors such as property().
This solution is only supported for a limited subset of python versions 3.9 and 3.10 and was buggy in those leading to it's removal in 3.11. See the 3.11 deprecation notes (link) and the Github issue discussion (gh-89519).
As far as I understand var is a class variable here:
class MyClass:
var = 'hello'
def __init__(self):
print(self.var)
And thats an instance variable:
class MyClass:
def __init__(self, var):
self.var = var
print(self.var)
I had the problem, that I was looking for a method to make type hinting possible for instance variables. I can of course typehint the parameter with def __init__(self, var: str): but that would not effect the instance variable itself.
Then I noticed in some descriptions (like here) that they used the term instance variable for a var like this:
class MyClass:
var : str = 'hello'
def __init__(self, var : str = None):
self.var = var if var
print(self.var)
That would be the solution indeed, but is that still an instance variable? Because it is defined in the class body, it would be a class variable in my understanding. If you would use a list for var, all alterations to this list-var would be shared over the instances.
But in this case there would be no problem, because the string is replaced and would not be shared for other instances. However, it seems wrong to me if you call it an instance variable and I don't know if I should use it like this just to have the type hinting working.
That would be the solution indeed, but is that still an instance variable? Because it is defined in the class body, it would be a class variable in my understanding. [...snip...] However, it seems wrong to me if you call it an instance variable and I don't know if I should use it like this just to have the type hinting working.
For what it's worth, I also share the same discomfort. It seems like we're conceptually mixing two concepts there just for the sake of having cleaner type annotations.
However, I've asked Guido one or two times about this, and it seems like he does indeed prefers treating those class attributes as if they were instance attributes.
In any case, to answer your core question, if we do this:
class Test:
field1: int
field2: str = 'foo'
Then...
PEP 484 and 526 compliant type checkers will treat this class as if:
It has an instance attribute named field1
It has an instance attribute named field2 that has a default value of 'foo' (as per PEP 526).
At runtime, ignoring type hints, Python will:
Add a class annotation named field1 to Test, but not a class attribute. (Class annotations are not automatically turned into class attributes.)
Add both a class annotation named field2 to Test as well as a class attribute named field2 containing the value 'foo'.
So, it can get a bit muddled.
But regardless, this then begs the question: how do we indicate to a type checker that we want some field to genuinely be a class attribute?
Well, it turns out PEP 484 was amended semi-recently to contain the ClassVar type annotation, which does exactly that.
So, if we wanted to add a new class attribute, we could do this:
from typing import ClassVar
class Test:
field1: int
field2: str = 'foo'
field3: ClassVar[int] = 3
So now, field3 should be treated as a class attribute with a default value of '3'.
(Note: ClassVar was added to typing for Python 3.5.3 -- if you're using the older version of typing bundled with Python 3.5, you can get a "backport" of the type by installing the typing_extensions third part module via pip and importing ClassVar from there instead.)
I think whether you decide to embrace this approach or not use it is a personal preference.
On one hand, Guido's opinion, pretty much by definition, defines what's "Pythonic" or not, so from that stance, there's no issue adopting this new idiom. Furthermore, the language itself is slowly but surely shifting to adopt this new idiom -- see the very recently accepted PEP 557, for example, which ends up following this same idiom of treating class attributes/class annotations as instance attributes.
On the other hand, it's difficult to shake off the nagging worry that this subtle difference will lead to issues down the line. In that case, you could stick with the standard approach of just setting all your fields inside __init__. This approach also has the benefit of keeping your code compatible with Python 2 and 3.x - 3.5.
A middle ground might be to just simply never use class attributes, in any way, shape, or form, and just stick to using class annotations. This is slightly restrictive, since we can no longer give our instance variables default values, but we can now avoid conflating class attributes with instance attributes entirely. (As previously stated, and as pointed out in the comments, class annotations are not added as class attributes.)
I downloaded a program to test on the laptop that only has python 2.4.4 on it and it keeps telling me syntax error on the parentheses of class main(): I have no experience with classes, so I am looking for a quick fix for this problem. How are classes different in python 2?
class main():
def __init__(self):
response=self.valid_input("New game or Load game?",["load","new"])
if response == "load":
the syntax is always on the ( part.
In python 2, There are two styles of classes, old and new, and they are different and not totally compatible with each other. In order to get new style classes (think classic OO class), they must explicitly inherit from object. Omitting the object inheritance is valid syntax but the class concept is not the same. So use:
class main(object): and know that it is not the same as class main:
In python 3, the object inheritance is implicit, so:
class main: is the same as class main(object): and is a new style class.
You should code with new style classes, as that is the future of Python and the only class style available in 3. See here for more detailed information.
Python class inherits object
I don't have a python2.4 interpreter to test this, but it seems that python2.4 you either don't use parenthesis class main: or you must specify at least one class to inherit from class main(object):
https://docs.python.org/release/2.4.4/ref/class.html
I am pondering if I should use inheritance or delegation to implement a kind of wrapper class. My problem is like this: Say I have a class named Python.
class Python:
def __init__(self):
...
def snake(self):
""" Make python snake through the forest"""
...
def sleep(self):
""" Let python sleep """
...
... and much more behavior. Now I have existing code which expects an Anaconda, which is almost like a Python, but slightly different: Some members have slightly different names and parameters, other members add new functionality. I really want to reuse the code in Python. Therefore I could do this with inheritance:
class Anaconda(Python):
def __init__(self):
Python.__init__(self)
def wriggle(self):
"""Different name, same thing"""
Python.snake(self)
def devourCrocodile(self, croc):
""" Python can't do this"""
...
Of course I can also call Anaconda().sleep(). But here is the problem: There is a PythonFactory which I need to use.
class PythonFactory:
def makeSpecialPython(self):
""" Do a lot of complicated work to produce a special python"""
…
return python
I want it to make a Python and then I should be able to convert it to an Anaconda:
myAnaconda = Anaconda(PythonFactory().makeSpecialPython())
In this case, delegation would be the way to go. (I don't know whether this can be done using inheritance):
class Anaconda:
def __init__(self, python):
self.python = python
def wriggle(self):
self.python.wriggle()
def devourCrocodile(self, croc):
...
But with delegation, I cannot call Anaconda().sleep().
So, if you're still with me, my questions are:
A) In a case similar to this, where I need to
add some functionality
rename some functionality
use "base class" functionality otherwise
convert "base class" object to "subclass" object
should I use inheritance or delegation? (Or something else?)
B) An elegant solution would be to use delegation plus some special method that forwards all attribute and method accesses which Anaconda does not respond to to its instance of Python.
B) An elegant solution would be to use delegation plus some special method that forwards all attribute and method accesses which Anaconda does not respond to to its instance of Python.
This is simple in Python, just define __getattr__:
class Anaconda:
def __init__(self, python):
self.python = python
def wriggle(self):
self.python.snake()
def devourCrocodile(self, croc):
...
def __getattr__(self, name):
return getattr(self.python, name)
See the Python docs on __getattr__
I read What is a metaclass in Python?
and I tried to replicate the upper metaclass from the example and found that this doesn't work in all cases:
def upper(cls_name, cls_parents, cls_attr):
""" Make all class attributes uppper case """
attrs = ((name, value) for name, value in cls_attr.items()
if not name.startswith('__'))
upper_atts = dict((name.upper(), value) for name, value in attrs)
return type(cls_name, cls_parents, upper_atts)
__metaclass__ = upper #Module level
class Foo:
bar = 1
f = Foo()
print(f.BAR) #works in python2.6
The above fails (with an attribute error) in python3 which I think is natural because all classes in python3 already have object as their parent and metaclass resolution goes into the object class.
The question:
How do I make a module level metaclass in python3?
The module level metaclass isn't really "module level", it has to do with how class initialization worked. The class creation would look for the variable "__metaclass__" when creating the class, and if it wasn't in the local environment it would look in the global. Hence, if you had a "module level" __metaclass__ that would be used for every class afterwards, unless they had explicit metaclasses.
In Python 3, you instead specify the metaclass with a metaclass= in the class definition. Hence there is no module level metaclasses.
So what do you do? Easy: You specify it explicitly for each class.
It's really not much extra work, and you can even do it with a nice regexp search and replace if you really have hundreds of classes and don't want to do it manually.
If you want to change all the attributes to upper case, you should probably use the __init__ method to do so, than use a metaclass.
Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
-- Python Guru Tim Peters
If you need something deeper, you should also evaluate using Class Decorators.
Using MetaClasses and understanding how the classes are created is so unnecessary as long as you want to do something that you can do using class decorators or initialization.
That said, if you really want to use a Metaclass tho' pass that as a keyword argument to the class.
class Foo(object, metaclass=UpperCaseMetaClass)
where UpperCaseMetaClass is a class that extends type and not a method.
class UpperCaseMetaClass(type):
def __new__():
#Do your Magic here.