Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
[SHARE CODE] doc strings from a class
-
I needed this function. I will eventually show it in a dialog. But I don't think the dialogs module has a dialog that this would be a correct fit for this data at the moment.
But yes it's an easy function. But a week ago, I would have struggled like hell to compose it.
Anyway, I decided to share it. I think it's related to Pythonista, especially if you are trying to write tools/Libs etc for others to use here.
I have called the function with a dict class. Also useful, but it's really meant to be called with your own classes.Again, I know it's trivial...
def get_docstrings_for_class(class_obj): ''' return the doc string or None For each attr in the passed class, if the attr does not startwith('_') and its callable return a tuple(attr, __doc__) in this case you expect attr to be a method of the class ''' return [ (attr, getattr(class_obj, attr).__doc__) for attr in dir(class_obj) if not attr.startswith('_') and callable(getattr(class_obj, attr))] if __name__ == '__main__': ds = get_docstrings_for_class(dict) print '\n'.join( '{h} {0} {h}\n {1}\n'.format(tp[0], tp[1], h = '#' * 5) for tp in ds)
-
Ok, also could have been written as:
if __name__ == '__main__': #ds = get_docstrings_for_class(tuple) print '\n'.join( '{h} {0} {h}\n {1}\n'.format(tp[0], tp[1], h = '#' * 5) for tp in get_docstrings_for_class(str))
-
print '\n'.join( '{h} {0} {h}\n {1}\n'.format(tp[0], tp[1], h = '#' * 5) # can be rewritten as: print('\n'.join('{h} {} {h}\n {}\n'.format(*tp, h = '#' * 5)) # ;-)
-
@ccc nice, i forget about unpacking! But at least i know about it now! I am getting there though, its getting a lot easy. I m also doing a unittest for the pragma class.
But thanks for the reply on the unpacking! -
@ccc, for extra guru points 😬, is there a solution for appending a item to a list inside a list comprehension. I have hit this issue a few times.
I can see 2 solutions, create and modify the list before the list comprehension or assign the list from the expression to a var then append to the list. Each is a bit different. I can understand why lists can't change inside a list comprehension, I thought the way I did it would create a new list once that is used to iterate over.
This is what I did,return [ (attr, getattr(class_obj, attr).__doc__) for attr in list(dir(class_obj).append('{}.__doc__'.format(str(class_obj)))) if not attr.startswith('_') or attr == '__init__' and callable(getattr(class_obj, attr))]
-
I am too heads down to provide you a full answer but I read thru http://treyhunner.com/2015/12/python-list-comprehensions-now-in-color last night and thought it might be of interest.
When I ever I get confused about comprehensions, I try to write them first as non-comprehensions to understand all that is going on in the logic and what order of execution is essential to getting the right answer.
Then I rewrite it as a comprehensions and test via
asset comprehension_way == non_comprehension_way, 'You messed up!'
. After you do this a dozen time, comprehensions are locked in your head and you can bang them out. -
@ccc , thanks again. I love the assert idea. As suggested in the article, if the comprehension is not in my head immediately, I start writing the for loop. But compared to a week ago, I am banging them out now. Ok, I missed the unpacking of the tuple. I remember when I first seen the syntax like *tp, I could only think of a pointer, then ** a de-referenced handle. Old habits die hard 😱
But thanks again, I will still keep working on it. -
Just because you can write something as a list comprehension does't mean you should. Remember
Readability counts
andSimple is better than complex
. Once your list comprehension is longer than a line or two, I think you gotta think about whether a for loop will be clearer. -
This post is deleted! -
Whether a comprehension is a good idea also depends on what you're trying to do. If you want to "transform" or filter items from a list or similar into a new list, then a comprehension is probably a good idea. If it gets more complex than that (e. g. one item might "become" multiple items, or if some operations have side effects) then it should probably be a normal
for
loop. -
Rob Pike one of the co-founders of the Go language at Google, talks in very interesting ways about the
There should be one-- and preferably only one --obvious way to do it.
across multiple languages in a recent Simplicity is Complicated presentation on programming language design. http://www.thedotpost.com/2015/11/rob-pike-simplicity-is-complicated Golang is much more deliberate in this regard than Python is. Some programmers from other languages find this minimalist approach confining but it really is useful when building massive codebases.At 05:10 into the talk he says "If a language has too many features, or even more than you might need, you spend time programming thinking about which features to use. If there are really a lot of features, you may look at a line of code, write it once way... Ohh, I could do something different, I could use this feature or that feature. You might even spend half an hour playing with a few lines of code to find all the right way to use different features to make the code to work in a certain way. And its kind of a waste of time to do that."
It is not the scale of programming that we tend to do in the Pythonista environment yet still it is a fascinating perspective.
-
For me, it's just important to be able to read and write them. (As well as dict and generator comps). The reading part is very important as some much sample code or answers via stack flow often are in the form of one of these comps. When they are 2nd nature, you have to read things many times over to get it.
I have found, since I am starting to get better with them solutions come very easy. I know the example I give above is over the top in term of how many statements are included, but really, it just looks bigger than it is really.
The premise of the question about deriving a new list inside a comp, I think is a very valid one. You can have the simplest of list comps, and all you need to do is add one item to the list dynamically.
If modify the list before the comp, looks messy, but at least you will get the same logic applied to all list items in the comp.You could also modify the list after the list comp is finished. Less desirable I think because you are by passing the list comps logic.
For me the best way would be if you inside the list comp you could generate the new list. I am starting thing it's not possible. As I mentioned before, I can understand why a list should not be growing inside a list comp, but with the right syntax so that a new list is created after modification and it's done before its used as an iterator you could imagine it's possible.
I haven't followed all @ccc advise yet about writing it out in full and see if that gives me a better understanding, but will do that soon.Anyway, from a beginners perspective with some previous computer language exp. I would say the earlier you can learn about list comps the better. Other things like .join gets demystified.
I mentioned the other day, I had just joined a Python group on Facebook. I was horrified at some of the advice that was being given. I put a sample below. Also in the the below, there where some other really bizarre suggestions.
I guess my point is you could do a lot worse than learning a lot about list comps in their different forms. I know that's not what is being said here. But I am finding by unlocking this door, other learning doors are opening easier. Again, in my beginners opinion, I think anyone new to Python with basic programming skills in another language should be taught these things first up.
I also want to say how lucky I feel to have been learning Python in Pythonista which brought me here were I have only had quality feedback and answers.
From Facebook, I am not trying to be smart. Just trying to point out how lucky we are here to have great people helping out.
Question
Can some one please let me know what may be the problem in this program. I am not getting any error but output is not getting displayed.Any help will be highly appreciated..#program, which will find all such numbers between 1000 and 3000 (both included) such that each digit of the number is an even number
L=[]
j=0
for i in range(1000,3001):
#Changing the integer to string to check each digit
s=str(i)
while (j<=len(s)):
if(int(s[j])%2==0):
j=j+1
L.append(s);
print L;Answer:
L=[]
for i in range(1000,3001):
s=str(i)
j=0while (j<len(s)):
if(int(s[j])%2==0):
flag=1
else:
flag=0
break#print j
j=j+1
if flag==1:
L.append(s)
print L;My answer:
def test():
return [str(i) for i in xrange(1000, 3001) if not i% 2]print test()
#i also mention generator syntax to reduce memory dependence -
YEAH I FOUND THE ANSWER
Hmmm, I am a little sad and embrassed it was so easy. But combining 2 lists together do the job....
It's not often you need to do this I think. But I think every now and then you need to add something at runtimedef foo(lst): return [i for i in lst + ['4', '5', '6']] lst = list(['1','2', '3']) print foo(lst)
-
The more correct example I should have done us
def foo(lst): return [i for i in lst + ['4', '5', '6']] def bar(lst): newlist = lst + ['4', '5', '6'] ret_list = [] for i in newlist: ret_list.append(i) return ret_list lst = list(['1','2', '3']) print foo(lst) print bar(lst) assert foo(lst) == bar(lst), 'Huston we have a problem'
-
@JonB , I answered you last night, but I was a little pissed so I deleted it 😱
Maybe you seen it. I just get emotional later into the night
But the crux of my message was, I do understand that list comps should not be written to the point where there are no longer comprehensible. I just think if I can take it to the max, then easy to back off. I have read about nested comps etc... Also the common view about making them to complex. The example I give before was not meant to be complex rather than just finding out how to append to a list inside a comp. -
I can see I probably neglected to include a winky grin in my response. I was intending a spirit of good natured ribbing, not insult.
-
@JonB , I know that. But I like when you guys are hard. It's the only way to learn. You need some tough love, sometimes. And it's appreciated. You and @ccc as well as other guys here have driven me crazy with some of your comments. But they are correct. May not understand at the time, but they becomes apparent over time.
-
@JonB , oops when I said pissed, I meant drunk, not angry 😇😱
Lol, I guess learning Python should be pretty easy compared to English.