I received this warning from PyCharm about an unresolved reference.
Here's code that is structured similarly, and should receive a warning as well.
class Parent:
"""
=== Attributes ===
#type public_attribute_1: str
"""
def __init__(self):
public_attribute_1 = ''
pass
class Child(Parent):
"""
=== Attributes ===
#type public_attribute_1: str
> Unresolved reference 'public_attribute_1'
#type public_attribute_2: str
"""
def __init__(self):
Parent.__init__(self)
public_attribute_2 = ''
pass
I understand that public_attribute_1 is not explicitly initiated in Child.__init__(), but Child.__init__() calls Parent.__init__(self) which initiates public_attribute_1. Thus the error raised concerns readability and documentation more than functionality.
How can I make such code more readable, without inserting redundancies, thereby defeating the whole point of inheritance?
Would it be sufficient to document thoroughly via docstrings and comments, and just ignore the warning from PyCharm? Or is there a pythonic way of doing it?
There are a number of issues here.
In Python 3 use super()
You are calling them "attributes", but this isn't how attributes work in Python. Glossing over details, use self.
Your question seems to be in regards to you want the docstring of Child to have all the attributes of Parent re-defined. This is pretty dangerous from a maintainability perspective though if anything ever changes. When I see a class inherits Parent, if I'm not familiar with Parent, I will go to the definition of Parent (which PyCharm makes easy with Ctrl + B).
I'll let someone else say if that's truly pythonic, but that's the way I'm used to working. Regardless, to fix your inheritance, your code should look more like this:
class Parent:
"""
=== Attributes ===
#type public_attribute_1: str
"""
def __init__(self):
self.public_attribute_1 = ''
class Child(Parent):
"""
=== Attributes ===
#type public_attribute_2: str
"""
def __init__(self):
super().__init__()
self.public_attribute_2 = ''
print(self.public_attribute_1)
Related
This is Python 3.10. My code is as follows:
from __future__ import annotations
from typing import Union
class Vehicle():
def __init__(self, components):
self.components = components
def getComponentWithFlag(self, flag: str) -> Union[Component,None]:
for component in self.components:
if getattr(component,flag,None):
return component
return None
class Component():
pass
class PassengerComponent(Component):
def __init__(self):
self.carriesPassengers = True
def ejectPassenger(self):
print('A passenger is tossed outside!')
class FreightComponent(Component):
def __init__(self):
self.carriesFreight = True
VW_Mini = Vehicle(components= [PassengerComponent()])
VW_Passat = Vehicle(components= [PassengerComponent(), FreightComponent()])
Truck = Vehicle(components= [FreightComponent()])
assert VW_Mini.getComponentWithFlag('carriesPassengers')
assert not VW_Mini.getComponentWithFlag('carriesFreight')
assert Truck.getComponentWithFlag('carriesFreight')
assert not Truck.getComponentWithFlag('carriesPassengers')
component = VW_Mini.getComponentWithFlag('carriesPassengers')
component.ejectPassenger()
Last line gives me a warning in PyCharm: Cannot find reference 'ejectPassenger' in 'Component | None'. I understand why it happens: there is no ejectPassenger method in Component class. Clearly the problem lies in how I typehint Vehicle.getComponentWithFlag method. Could you guys tell me how I should type hint its return object?
I know the object returned by that function:
may be None (if there's no appropriate Component),
may be an object of a subclass inheriting from Component class,
will never actually be an object of Component class itself.
Type hinting it explicitly like this: def getComponentWithFlag(self, flag: str) -> Union[PassengerComponent, FreightComponent, None] will not fly, because I will eventually have dozens of Components in my actual use-case and I would prefer to avoid typing them all out.
I would prefer to avoid typing them all out.
Unfortunately, I don't think it is possible, as you can't exclude root type only. (i.e. You can't hint all subclasses of T without T, as T is also subclass of T in static typing)
Instead, you can overload Vehicle.getComponentWithFlag.
from __future__ import annotations
from typing import Optional, Literal, Union, overload
class Vehicle():
def __init__(self, components):
self.components = components
#overload
def getComponentWithFlag(self, flag: Literal["carriesPassengers"]) -> Optional[PassengerComponent]:
...
#overload
def getComponentWithFlag(self, flag: Literal["carriesFreight"]) -> Optional[FreightComponent]:
...
def getComponentWithFlag(self, flag: str) -> Union[Component, None]:
for component in self.components:
if getattr(component,flag,None):
return component
return None
Try this code in your IDE. This code has limitation that you have to maintain overloaded variants as number of subclasses increases. However, I think this is optimal for now.
I'm a structured programming guy. So my attempts with object oriented programming are always "work in progress..."
My intent is to have a class which will adapt itself according to an external input. I saw in another post (which I was unable to find again) that I can change the class of an object, so I made this MWE, which works:
class Base:
def __init__(self, name):
self.name = name
def set_text(self, text):
self.text = text
class Terminator(Base):
terminator = '!'
def __init__(self):
super().__init__('terminator')
def get(self):
return self.text + terminator
class Prefix(Base):
def __init__(self):
super().__init__('prefix')
def get(self):
return str(len(self.text)) + self.text
class_list = {
'terminator': Terminator,
'prefix': Prefix
}
class Selector():
def __init__(self, option):
self.__class__ = class_list[option]
def main():
selection = input("Choose 'terminator' or 'prefix': ")
obj = Selector(selection)
obj.set_text('something')
print(obj.get())
if __name__ == '__main__':
main()
Terminator is a class to produce a text terminated with a special character (!); Prefix produces the same text prefixed with its length.
With Selector, I can use o = Selector('prefix') to get o as a Prefix instance.
The question
My question is if I can add extra arguments to Selector and pass them to the respective class. For example:
o = Selector('prefix', number_of_digits = 2) # '05hello' intead of '5hello'
or
o = Selector('terminator', terminator = '$') # use '$' instead of '!'
For now, I couldn't figure out how to accomplish this task. I tried to use *args and **kwargs, but unsuccessfully.
Additional information
The code I'm working on is intended to undergraduate students and I want to make it simple for teaching purposes, so Selector should be used to hide other classes and their details from the students (to hide Terminator and Prefix, for example).
I expect to have about 15 distinct classes to hide behind Selector.
Also, I'm ready to hear I'm completely wrong about this approach if there are alternatives.
Try calling the appropriate class's __init__() manually, and set the variables like you otherwise would:
class Terminator(Base):
# make terminator an instance variable instead of a class variable,
# and set it as an overridable default arg for the constructor
def __init__(self, terminator='!'):
super().__init__('terminator')
self.terminator = terminator
def get(self):
return self.text + self.terminator
class Selector():
def __init__(self, option, *args, **kwargs):
self.__class__ = class_list[option]
self.__class__.__init__(self, *args, **kwargs)
...
o = Selector('terminator', terminator='$')
o.set_text("Hello World")
print(o.get())
# Hello World$
I should leave a disclaimer: what you're trying to do is essentially a version of the Factory method pattern, which is usually easier to maintain if you bundle it into a method instead of messing with class types and reflection:
def Selector(option: str, *args, **kwargs) -> Base:
return class_list[option](*args, **kwargs)
# this will do .__new()__ and .__init__() normally,
# and is indistinguishable from normal class creation
Using a method to do this instead of overriding the class metadata also has the advantage of being easy to fit into a type system (see the type hinting in the above snippet), which is difficult to do with .__init__(). This is a common design pattern in Java, for example, which is very strongly and statically typed, requires a factory method to have a signature with the superclass of anything it could possibly return, and makes it impossible for an object to change its own type at runtime.
The disadvantage of your current approach, dynamically changing .__class__, is that the .__new__() and .__init__() methods which were called on the resulting object will not match with each other (it would be using Selector.__new__() but Terminator.__init__(), for example), which may cause weird and hard-to-diagnose problems in the future. It's a fun experiment, but be knowledgeable of the risks before using this in something you'll have to maintain for a long time.
I'm using Python 3.7 and PyCharm 2019.1.3, I've made a subclass of UserString and althought the documentation clearly states I should be able to access the underlying string with myinstance.data PyCharm shows me an Unresolved attribute reference 'data' for class 'Token'.
Here's my subclass:
from collections import UserString
class Token(UserString):
def __init__(self, value, is_emoji: bool):
# if it's not an emoji and a title we lower-case the value
UserString.__init__(self, value.lower() if not is_emoji and value.istitle() else value)
self.is_emoji: bool = is_emoji
if __name__ == '__main__':
token = Token("Sauce", False)
print(token.data)
is it a PyCharm bug or am I doing something wrong ?
Since I can correctly print(token.data) in your example, this indeed must be a bug in PyCharm.
You can try to sidestep it by using super which likely would trigger a different code analysis path and discover the .data member. Did not try it, though.
I'm wondering if I have:
class A(object):
def __init__(self):
self.attribute = 1
self._member = 2
def _get_member(self):
return self._member
def _set_member(self, member):
self._member = member
member = property(_get_member, _set_member)
class B(object):
def __init__(self):
self._member = A()
def _get_a_member(self):
return self._member.member
def _set_a_member(self, member):
self._member.member = member
member = property(_get_a_member, _set_a_member)
Can I somehow avoid to write get/setters for A.member, and simply refer to the attribute or property of the A object?
Where the get/setters do logic, its of course needed, but if I simply wan't to expose the member/attributes of a member attribute, then writing get/setters seems like overhead.
I think even if I could write the get/setters inline that would help?
I find the question a bit unclear, however I try to explain some context.
Where the get/setters do logic, its of course needed, but if I simply wan't to expose the member/attributes of a member attribute
If there is no logic in getter/setters, then there is no need to define the attribute as a property, but the attribute can be used directly (in any context).
So
class A(object):
def __init__(self):
self.attribute = 1
self.member = 2
class B(object):
def __init__(self):
self.member = A()
B().member.member # returns 2
B().member.member = 10
In some languages, it's considered good practice to abstract instance properties with getter/setter methods, That's not necessarily the case in Python.
Python properties are useful when you'd need more control over the attribute, for example:
when there is logic (validation, etc.)
to define a readonly attribute (so only providing a getter without a setter)
Update (after the comment)
properties are not necessarily a tool to "hide" some internal implementation. Hiding in Python is a bit different than say in Java, due to very dynamic nature of Python language. It's always possible to introspect and even change objects on the fly, you can add new attributes (even methods) to objects on runtime:
b = B()
b.foo = 4 # define a new attribute on runtime
b.foo # returns 4
So Python developers rely more on conventions to hint their intentions of abstractions.
About the polymorphic members, I think it's most natural for Python classes to just share an interface, that's what's meant by Duck typing. So as long as your next implementation of A supports the same interface (provides the same methods for callers), it should not be any issue to change its implementation.
So this is what I came up with - use a method to generate the properties, with the assumption that the obj has an attribute of _member:
def generate_cls_a_property(name):
"""Small helper method for generating a 'dumb' property for the A object"""
def getter(obj):
return getattr(obj._member, name)
def setter(obj, new_value):
setattr(obj._member, name, new_value)
return property(getter, setter)
This allows me to add properties like so:
class B(object):
def __init__(self):
self._member = A()
member = generate_cls_a_property('member') # generates a dumb/pass-through property
I'll accept my own, unless someone tops it within a week.. :)
I'm having some doubts with the design of mutiple inheritance in some Python classes.
The thing is that I wanted to extend the ttk button. This was my initial proposal (I'm omitting all the source code in methods for shortening, except init methods):
import tkinter as tk
import tkinter.ttk as ttk
class ImgButton(ttk.Button):
"""
This has all the behaviour for a button which has an image
"""
def __init__(self, master=None, **kw):
super().__init__(master, **kw)
self._img = kw.get('image')
def change_color(self, __=None):
"""
Changes the color of this widget randomly
:param __: the event, which is no needed
"""
pass
def get_style_name(self):
"""
Returns the specific style name applied for this widget
:return: the style name as a string
"""
pass
def set_background_color(self, color):
"""
Sets this widget's background color to that received as parameter
:param color: the color to be set
"""
pass
def get_background_color(self):
"""
Returns a string representing the background color of the widget
:return: the color of the widget
"""
pass
def change_highlight_style(self, __=None):
"""
Applies the highlight style for a color
:param __: the event, which is no needed
"""
pass
But I realized later that I wanted also a subclass of this ImgButton as follows:
import tkinter as tk
import tkinter.ttk as ttk
class MyButton(ImgButton):
"""
ImgButton with specifical purpose
"""
IMG_NAME = 'filename{}.jpg'
IMAGES_DIR = os.path.sep + os.path.sep.join(['home', 'user', 'myProjects', 'myProject', 'resources', 'images'])
UNKNOWN_IMG = os.path.sep.join([IMAGES_DIR, IMG_NAME.format(0)])
IMAGES = (lambda IMAGES_DIR=IMAGES_DIR, IMG_NAME=IMG_NAME: [os.path.sep.join([IMAGES_DIR, IMG_NAME.format(face)]) for face in [1,2,3,4,5] ])()
def change_image(self, __=None):
"""
Changes randomly the image in this MyButton
:param __: the event, which is no needed
"""
pass
def __init__(self, master=None, value=None, **kw):
# Default image when hidden or without value
current_img = PhotoImage(file=MyButton.UNKNOWN_IMG)
super().__init__(master, image=current_img, **kw)
if not value:
pass
elif not isinstance(value, (int, Die)):
pass
elif isinstance(value, MyValue):
self.myValue = value
elif isinstance(value, int):
self.myValue = MyValue(value)
else:
raise ValueError()
self.set_background_color('green')
self.bind('<Button-1>', self.change_image, add=True)
def select(self):
"""
Highlights this button as selected and changes its internal state
"""
pass
def toggleImage(self):
"""
Changes the image in this specific button for the next allowed for MyButton
"""
pass
The inheritance feels natural right to his point. The problem came when I noticed as well that most methods in ImgButton would be reusable for any Widget I may create in the future.
So I'm thinking about making a:
class MyWidget(ttk.Widget):
for putting in it all methods which help with color for widgets and then I need ImgButton to inherit both from MyWidget and ttk.Button:
class ImgButton(ttk.Button, MyWidget): ???
or
class ImgButton(MyWidget, ttk.Button): ???
Edited: Also I want my objects to be loggable, so I did this class:
class Loggable(object):
def __init__(self) -> None:
super().__init__()
self.__logger = None
self.__logger = self.get_logger()
self.debug = self.get_logger().debug
self.error = self.get_logger().error
self.critical = self.get_logger().critical
self.info = self.get_logger().info
self.warn = self.get_logger().warning
def get_logger(self):
if not self.__logger:
self.__logger = logging.getLogger(self.get_class())
return self.__logger
def get_class(self):
return self.__class__.__name__
So now:
class ImgButton(Loggable, ttk.Button, MyWidget): ???
or
class ImgButton(Loggable, MyWidget, ttk.Button): ???
or
class ImgButton(MyWidget, Loggable, ttk.Button): ???
# ... this could go on ...
I come from Java and I don't know best practices for multiple inheritance. I don't know how I should sort the parents in the best order or any other thing useful for designing this multiple inheritance.
I have searched about the topic and found a lot of resources explaining the MRO but nothing about how to correctly design a multiple inheritance. I don't know if even my design is wrongly made, but I thought it was feeling pretty natural.
I would be grateful for some advice, and for some links or resources on this topic as well.
Thank you very much.
I've been reading about multiple inheritance these days and I've learnt quite a lot of things. I have linked my sources, resources and references at the end.
My main and most detailed source has been the book "Fluent python", which I found available for free reading online.
This describes the method resolution order and design sceneries with multiple inheritance and the steps for doing it ok:
Identify and separate code for interfaces. The classes that define methods but not necessarily with implementations (these ones should be overriden). These are usually ABCs (Abstract Base Class). They define a type for the child class creating an "IS-A" relationship
Identify and separate code for mixins. A mixin is a class that should bring a bundle of related new method implementations to use in the child but does not define a proper type. An ABC could be a mixin by this definition, but not the reverse. The mixin doesn't define nor an interface, neither a type
When coming to use the ABCs or classes and the mixins inheriting, you should inherit from only one concrete superclass, and several ABCs or mixins:
Example:
class MyClass(MySuperClass, MyABC, MyMixin1, MyMixin2):
In my case:
class ImgButton(ttk.Button, MyWidget):
If some combination of classes is particularly useful or frequent, you should join them under a class definition with a descriptive name:
Example:
class Widget(BaseWidget, Pack, Grid, Place):
pass
I think Loggable would be a Mixin, because it gathers convenient implementations for a functionality, but does not define a real type. So:
class MyWidget(ttk.Widget, Loggable): # May be renamed to LoggableMixin
Favor object composition over inheritance: If you can think of any way of using a class by holding it in an attribute instead of extending it or inheriting from it, you should avoid inheritance.
"Fluent python" - (Chapter 12) in Google books
Super is super
Super is harmful
Other problems with super
Weird super behaviour
In principle, use of multiple inheritance increases complexity, so unless I am certain of its need, I would avoid it. From your post you already look aware of the use of super() and the MRO.
A common recommendation is to use composition instead of multiple inheritance, when possible.
Another one is to subclass from only one instantiable parent class, using abstract classes as the other parents. That is, they add methods to this subclass, but never get instantiated themselves. Just like the use of interfaces in Java. Those abstract classes are also called mixins, but their use (or abuse) is also debatable. See Mixins considered harmful.
As for your tkinter code, besides logger code indentation, I don't see a problem. Maybe widgets can have a logger instead of inheriting from it. I think with tkinter the danger is the unwanted override by mistake of one of the hundreds of available methods.