Problem: I want to use one docstring in another docstring.
Suppose I have the following snippet:
def window(dimensions: tuple):
'''
Function to create an app window and return it
PARAMETERS
----------
dimensions : tuple
The width and height of the window to create
RETURNS
-------
display.Window
Class to implement a screen # Make this equal to Window.__doc__
'''
class Window:
'''
Class to implement a screen
'''
def __init__(self, dimensions: tuple):
pass
return Window(dimensions)
I want to automatically set the docstring for window to include the docstring for Window
I read that you can set the docstring manually, like so:
window.__doc__ = "".join((window.__doc__, Window.__doc__))
But it is only executed when the function is called.
Also, I could use decorators, but is there a simpler intuitive way to do this?
Bonus: Is there a way to decide exactly where in the docstring I can include another?
EDIT: So, it looks like there is a duplicate suggestion to this question, but since I specifically asked without decorators, that does make my question somewhat different. Also, my use of nested class in window means that any attempt to change __doc__:
inside of window: will not occur until function is called.
outside of window: will not run as Window is nested.
So this rules both these methods out, as things stand.
But the answer of course has to be one of these. So the answer is a duplicate, not the question. :P
Therefore, I had to restructure my code. See below.
Thanks to #aparpara, I found that answer (which didn't show up when I searched it online), and it made me realise there is (possibly?) no solution to my specific question.
Therefore, I had to remove the nested class to be able to access it outside the function.
Here is the final version.
# module display_module.py
class Window:
'''
Class to implement pygame's screen
'''
def __init__(self, dimensions: tuple):
pass
def window(dimensions: tuple):
'''
Function to create an app window and return it
PARAMETERS
----------
dimensions : tuple
The width and height of the window to create
RETURNS
-------
display.Window
{0}
'''
return Window(dimensions)
window.__doc__ = window.__doc__.format(Window.__doc__.strip())
Still open to any answers to the old question!
Related
I try to create a proper container Class for Gtk in Python (MyBin in the code below). There seems to be no authoritative documentation on how to do that, only bits and pieces, which I glued together with trial and error. – There are many open questions, but let me focus on size_allocate() here:
What is the the original size_allocate() function doing? And what is my overlaid version in my container class supposed to do?
I already do 95% know that I have to replace the original method with my own by prepending “do_” to form the do_size_allocate() method (by trial and error – see code below; I could not find anything talking about all those “do_*” functions).
I found so far, that calling self.set_allocation(allocation) seems to be a good idea as is self.get_child().size_allocate(...) to give the child some working space (see code). – Any other obligations I have to fulfill? What is the original function doing additionally?
Regarding the allocation I pass down to the child: I need to adapt it (not in the code below yet). I successfully(?) used a fresh Gdk.Rectangle() on which I set x, y, width and height, but I somehow feel that it’s wrong and something with (do_)adjust_size_allocation() should be used instead. But how?
Lets look into the documentation of do_size_allocate():
This function is only used by Gtk.Container subclasses, to assign a
size and position to their child widgets. [“Only used”? Only called from? Only implemented at? Only overwritten by? – Well, I’m doing it already, but the doc wasn’t helpful in finding out how.]
In this function, the allocation may be adjusted. [How?] It will be forced to
a 1x1 minimum size [Can confirm only that get_allocation() will return a 1x1 if I don’t set anything.],and the adjust_size_allocation virtual method on
the child will be used to adjust the allocation. [What? For my own allocation? Or for the one I set on the child via ...get_child().size_allocate()? Who calls that adjust method? In which conditions is it not called before size_allocate()?] Standard adjustments
include removing the widget’s margins, and applying the widget’s
Gtk.Widget :halign and Gtk.Widget :valign properties.
#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class MyBin(Gtk.Bin):
def __init__(self):
super().__init__()
def do_size_allocate(self, allocation):
print('PARENT METHOD do_size_allocate', allocation.width)
# if not called, `get_allocation()` in `do_draw()` will return a 1x1 rectangle
self.set_allocation(allocation)
# strangely required so that `do_draw()` will be called even on this class!
self.get_child().size_allocate(allocation)
def do_draw(self, c):
allocation = self.get_allocation()
print('PARENT do_draw()', allocation.width)
self.propagate_draw(self.get_child(), c)
class MyChild(Gtk.Button):
def __init__(self):
super().__init__()
self.connect('size-allocate', self.size_allocate_handler)
self.connect('draw', self.draw_handler)
def size_allocate_handler(self, self2, allocation):
print('CHILD signal size-allocate', allocation.width)
def draw_handler(self, self2, c):
allocation = self.get_allocation()
print('CHILD signal draw', allocation.width)
class MainWindow(Gtk.Window):
def __init__(self):
super().__init__(title='d2see test pattern')
the_child = MyChild()
my_container = MyBin()
my_container.add(the_child)
self.add(my_container)
self.show_all()
if __name__ == '__main__':
MainWindow()
Gtk.main()
First question on SO! Bear with me, there is a bit of background context needed.
I started using classes to make a data storage container similar to struct in matlab. When going open source with Python, I have not completely replaced this and it is very useful when combining more than just numeric array data, or just makes more sense to reference things with names instead of indicies.
I realized using classes was not the best thing to do for several layers deep (right? mostly just confusing and maybe slow), and I need a generic tree data type. I am working on a project to automate Excel, and data must be stored based on what is in the cell, later operated on, and potentially rewritten back to some areas of the spreadsheet. And who wants to write in VBA when we can use xlwings and openpyxl to leverage other stuff we have written in an adaptable, OS portable language like Python?!
Building upon this post:
Looking for a good Python Tree data structure
I liked the expandability of this:
import collections
def Tree():
return collections.defaultdict(Tree)
I can make arbitrary layers of any type. I also wanted to also include some functions to manage it like I had in my class storage containers as demonstrated in the UserData class at the bottom of this post. There is an example of it being used in a class on that pagewhich sort of works:
class Tree(defaultdict):
def __call__(self):
return Tree(self)
def __init__(self, parent):
self.parent = parent
self.default_factory = self
So I experimented, worked out kinks, and made this class:
import collections
class TreeClass(collections.defaultdict):
def __call__(self):
return TreeClass(self)
def Tree(self):
return collections.defaultdict(self.Tree)
def __init__(self, parent):
self.parent = parent
self.default_factory = self
#self.x = 'xvar'
#self._locations_idx=[]
self['someInitKey'] = 'value'
The reason I want the class and the functionality of the data structure operating on itself is to do something like this:
import openpyxl.utils as opx
class UserData():
'''For more info on decorators:
https://stackoverflow.com/questions/27571546/dynamically-update-attributes-of-an-object-that-depend-on-the-state-of-other-att
https://stackoverflow.com/questions/17330160/how-does-the-property-decorator-work
'''
def __init__(self):
self.locations=[]
self._locations_idx=[]
#property # Auto update locations_idx when locations changes
def locations_idx(self):#, locations=self.locations):
self._locations_idx = self.locations # set list to same len
for i in range(len(self.locations)):
current_loc = self.locations[i]
# write indexed location over copy of list of same len
# TODO check make sure this is zero indexed
self._locations_idx[i] = (opx.column_index_from_string(current_loc[0]), int(current_loc[1]))
return self._locations_idx
where opx.column_index_from_string is a function from openpyxl to return the corresponding 0-indexed index from a letter, and it is combined into a tuple to turn a list of 'A1', 'B2' into a list of (0,0), (1,1) etc
This way, though the class is initialized with an empty locations list, when the list is populated with 'C4', 'B22' etc, the myUserData.locations_idx contains an updated list of these indices which are very useful for the rest of the program when you don't want to reference contents by 'excel location'.
Now for my actual question:
Say I use this to make a default dict of schema defaultdict[carMake][carModel][carColor][locationInSpreadsheet] like following:
myUserData['toyota']['corolla']['grey']['location']='B2'
myUserData['chevy']['Volt']['blue']['location']='B6'
and upon adding a 'location' key/value, I would like to dynamically create corresponding:
myUserData['chevy']['Volt']['blue']['location_idx']
which returns (1,5).
Only thing is I am new to default_dict, rarely need to OOP Python, not sure what to even google (referencing many layers into a tree data structure made from default dict python ?). Can someone help or give me some pointers? I hate to drag on other people and have made it a long way in Python without needing to ask a question on here, but I've hit my limit when I don't even know what to look for. I hope you can tell what I'm trying to do from the examples, and I think I'm approaching this problem the right way. Any post formatting/etiquette, tag suggestions, are welcome too. If something is unclear, please let me know, but I have tried to make the examples general enough and easy to understand that someone who works with Python classes and default dicts should be able to understand. I think. Thanks for any help!
Below is a sketch of a class I want to document.
My first wish is to get short help from within Jupyter.
These help calls work as I expected:
help(thermo): showing everything (class, methods and properties)
help(thermo.select): showing the select help
help(thermo.table): showing the table help
Unfortunately, this one doesn't work as I would expect:
help(thermo.take) does not return the help from the take property.
Instead, this statement returns all the attributes from the take object. (2000+)
Could you clarify what happens,
and suggest me how to get help(thermo.take) working as I would like?
Thanks
class substances(list, metaclass=substancesMeta):
''' A thermodynamic database of substances '''
#property
def take(self):
''' A simple way to take a substance. '''
def select(self, ... ):
''' Select a subset of the database. '''
def table(self, **kwargs):
''' Create a pandas dataframe from substances object '''
The point of properties is that thermo.take gets you the object returned by the getter (in this case, a Take object). That's why help(thermo.take) is equivalent to help(Take()) (or whatever your "take object" is).
You can bypass this behavior by calling help on the property of the class:
help(substances.take)
# Or
help(type(thermo).take)
This works because there's no self upon which you're calling take, so the only thing it has to return is your defined property.
I've written a script that solves sudoku problems.
To model each slot of a grid, I have in a first time defined Slot and Grid classes like this (complete code elipsed for the sake of simplicity :
class Slot():
def __init__(self,grid):
self.grid = grid
self.values = list(range(9))
def pos(self):
return self.grid.index(self)
class Grid(list):
def __init__(self):
for i in range(9*9):
self.append(Slot(self))
Like this, I can define method for my Slot class using self.pos() and self.values(). For example :
g = Grid()
g[5].pos() -> returns 5, OK !
Now that my full script works just fine, I want to refactor it, and, as a Slot is basically a list belonging to a Grid, I decided it would be great for my Slot to subclass list, like this :
class Slot(list):
def __init__(self,grid):
self.grid = grid
self.append(list(range(9)))
def pos(self):
return self.grid.index(self)
class Grid(list):
def __init__(self):
for i in range(9*9):
self.append(Slot(self))
g = Grid()
g.index(g[5]) -> returns 0, KO !
I've tried to init the list first ie: super().init(list(range(9)), and also a few variations, but nothing seems to work.
What am I missing ?
PS : the g.index(g[5]) is just to describe, I'm aware it's pointless. I'm using this logic in methods inside my objects (self.pos(), etc.)
By making Slot a subclass of list you also make the comparison between Slot instances use the logic defined for lists (since you haven't overridden that).
Since all Slots contain the same value:
self.append(list(range(9)))
g.index() will simply match the first entry the grid yielding 0 as the result.
When you inherited from object (as Slot did in your first example) all instances compared unequal to themselves as is defined in the Python Reference (unless logic is implemented that dictates otherwise).
In short, you'll need to redefine the comparison methods if you need the slots with similar items to be treated differently when compared. In addition to that, you might want to reconsider sub classing from list and, instead, opt for UserList from collections.
I'm building a PyQt QGraphicsView project where some QGraphicItems can be moved around between different QGraphicsItemGroups. For that, I use the addItemToGroup() method of the "new" parent itemGroup.
This works fine, but only so long as I do not define the itemChange() method in my custom child-item class. Once I define that method (even if I just pass the function call to the super class), the childItems will not be added to ItemGroups no matter what I try.
class MyChildItem(QtGui.QGraphicsItemGroup):
def itemChange(self, change, value):
# TODO: Do something for certain cases of ItemPositionChange
return QtGui.QGraphicsItemGroup.itemChange(self, change, value)
#return super().itemChange(change, value) # Tried this variation too
#return value # Tried this too, should work according to QT doc
Am I simply too stupid for properly calling a superclass method in Python, or is the problem somewhere in the QT / PyQT magic?
I use Python 3.3 with PyQt 4.8 and QT 5.
I had the exact same problem. Maybe this: http://www.mail-archive.com/pyqt#riverbankcomputing.com/msg27457.html answers some of your questions?
Seems like we might be out of luck in PyQt4.
Update:
Actually, just found a workaround:
import sip
def itemChange(self, change, value):
# do stuff here...
result = super(TestItem, self).itemChange(change, value)
if isinstance(result, QtGui.QGraphicsItem):
result = sip.cast(result, QtGui.QGraphicsItem)
return result
taken from here: http://www.mail-archive.com/pyqt#riverbankcomputing.com/msg26190.html
Maybe not the most elegant and general solution, but over here, it works -- I'm able to add QGraphicItems to QGraphicItemGroups again.