Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
breaks
May 12, 2001

I disagree, the right way to do it is explicitly checking against None. '' is false, 0 is false, [] is false, lots of things that you could potentially want to accept, if not in this specific situation then in other similar ones, are false. self.x = x or y will bite you in the rear end sooner or later, self.x = x if x is not None else y is safe.

Adbot
ADBOT LOVES YOU

Pollyanna
Mar 5, 2005

Milk's on them.


Haystack posted:

.sort() sorts the list in place and returns None. You want:

Python code:
>>> reversed = close.copy()
>>> reversed.sort(ascending=False) #Should at least attempt to reverse the list
>>> print(reversed)

I'm actually realizing that I want something else. Sorry :ohdear: Now that I look at it, what I want to do is flip the associations between date and values, so that:

code:
[100   200   300   400   500  ]
[1     2     3     4     5    ]
becomes

code:
[500  400   300   200   100  ]
[1    2     3     4     5    ]
Since there's the same amount of values and indices, then it should work. How do you do this for a Series?

Symbolic Butt
Mar 22, 2009

(_!_)
Buglord

breaks posted:

I disagree, the right way to do it is explicitly checking against None. '' is false, 0 is false, [] is false, lots of things that you could potentially want to accept, if not in this specific situation then in other similar ones, are false. self.x = x or y will bite you in the rear end sooner or later, self.x = x if x is not None else y is safe.

Yeah, I agree with this and I'm almost sure no one calls this pythonic and the only place I remember the guy was recommending using this "or pattern" was in Dive into Python which is a book full of weird advice.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

A Violence Gang posted:

Thanks, that all makes a lot of sense! As for

I forgot to mention that hypothetically I'd like these lists to be easily edited by or even shared among users. (Not that this novice code of a half-baked idea is actually going anywhere, just in principle.) So that made these lists seem like "data" rather than "code". I've been learning from Dive into Python 3 which emphasized that distinction, though I don't know if I'm applying it correctly.

I forgot to mention in my last post that Dive into Python is pretty much anti-recommended in this thread.

For text-based learning these are probably the best recommendations (copy-pasted from the new OP I'm working on):

Think Python: How To Think Like A Computer Scientist [http://www.greenteapress.com/thinkpython/]
There’s a link there to read it online without paying anything.

Learn Python The Hard Way [http://learnpythonthehardway.org/]
There’s a link there to read it online without paying anything.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

A Violence Gang posted:

Thanks, that's much easier. One more question -- there's a more idiomatic way to do this, isn't there?
Python code:
def __init__(self, name = ''):
    if name:
        self.name = name
    else:
        self.name = random.choice(names)

My answer: don't do this. Randomly choosing from a bunch of names should not be something your constructor does if you don't pass in anything. Make a factory method:

Python code:
class Duder(object):
    def __init__(self, name):
        self.name = name

    @classmethod
    def make_random_duder(cls):
        name = random.choice(names)
        return cls(name)

Lurchington
Jan 2, 2003

Forums Dragoon

Symbolic Butt posted:

Yeah, I agree with this and I'm almost sure no one calls this pythonic and the only place I remember the guy was recommending using this "or pattern" was in Dive into Python which is a book full of weird advice.

There's a lot of code-reviewed production code on my team that makes use of the

Python code:
def Butts(object):
    def __init__(self, farts=None):
        self.farts = farts or []
and it comes down to the answer to the answer to the question: "is there a single falsey but valid value other than empty list for this instance variable?"

If the answer is no, we've found the above code is simpler and less likely to trick your brain into having to actually analyze the whole line in case it's more than an assignment with a mutable default value.

if the answer is yes, then sure, go with your choice of:
Python code:
def Butts(object):
    def __init__(self, farts=None):
        self.farts = farts if farts is not None else []  # or however you want the ternary
or:
Python code:
def Butts(object):
    def __init__(self, farts=None):
        if farts is None:
            self.farts = []
        else:
            self.farts = farts
our team edges towards the first, because other folks like conserving vertical line space

KICK BAMA KICK
Mar 2, 2009

OK, I can see how this does cool stuff in the case where I'm subclassing the thing we're talking about (which I am). The subclasses all inherit the factory method, you can define names in the parent class, override it in the subclass if one needs a unique list of random choices and that'll all work since cls will refer to the subclass if you call it that way. That's cool, it factors out the common stuff that all the subclasses need to do at initialization but means you can still do unique stuff in each subclass's constructor (or, I suppose, they can also have their own factory methods).

But aside from the benefits a factory method provides when used in a parent class, I'm a little unclear on:

Suspicious Dish posted:

Randomly choosing from a bunch of names should not be something your constructor does if you don't pass in anything.
Does that mean it's bad to randomize parameters when they don't get passed (and hence your example factory method explicitly creates an object with random parameters, rather than accepting arguments and employing that if... else logic)? Or that it's just bad to do so in the constructor itself (like there's a convention that constructors should just do simple assignment and logic should go elsewhere)?

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
I think it's a bad API in general. Simple defaults so that callers can omit things in the common case are OK, but having a sophisticated fallback with logic seems wrong. Explicit is better than implicit.

QuarkJets
Sep 8, 2008

A Violence Gang posted:

Thanks, that all makes a lot of sense! As for

I forgot to mention that hypothetically I'd like these lists to be easily edited by or even shared among users. (Not that this novice code of a half-baked idea is actually going anywhere, just in principle.) So that made these lists seem like "data" rather than "code". I've been learning from Dive into Python 3 which emphasized that distinction, though I don't know if I'm applying it correctly.

They'd be very easy to edit and share between users. Here's an example:

Python code:
names = (
"George",
"Martin",
"Greg",
"Michael",
"Susan",
"Miranda"
)
One of Python's greatest advantages is that it's so often very easy to read and understand. Put that line in a file called "all_names.py". Share it, edit it, do whatever. You could probably even parse this with a bash script pretty easily, if you wanted to. Anytime that you need the names list, just type 'from all_names import names' and you're done.

Dren
Jan 5, 2001

Pillbug

Pollyanna posted:

I'm actually realizing that I want something else. Sorry :ohdear: Now that I look at it, what I want to do is flip the associations between date and values, so that:

code:
[100   200   300   400   500  ]
[1     2     3     4     5    ]
becomes

code:
[500  400   300   200   100  ]
[1    2     3     4     5    ]
Since there's the same amount of values and indices, then it should work. How do you do this for a Series?

Python code:
df = pd.DataFrame({'values' : [100, 200, 300, 400, 500], 'time' : [1, 2, 3, 4, 5]})
df['values'] = df['values'].values[::-1]

Jewel
May 2, 2009

QuarkJets posted:

They'd be very easy to edit and share between users. Here's an example:

Python code:
names = (
"George",
"Martin",
"Greg",
"Michael",
"Susan",
"Miranda"
)
One of Python's greatest advantages is that it's so often very easy to read and understand. Put that line in a file called "all_names.py". Share it, edit it, do whatever. You could probably even parse this with a bash script pretty easily, if you wanted to. Anytime that you need the names list, just type 'from all_names import names' and you're done.

Yeah but hardcoding poo poo is dumb and you should basically never do it??? What if you want to load the names from a webserver or don't want to have to type "<name>", every time you want to add a new name. Or have a list of names you got from somewhere that you just want to copypaste in (I know you can easily write a script to add the commas and quotes but that's not the point).

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Hardcoding stuff is fine for testing. You can easily read names from a file at runtime, too.

Also, Quark, you didn't show off the best feature:

Python code:
names = (
"George",
"Martin",
"Greg",
"Michael",
"Susan",
"Miranda",
)
You can put a comma at the end there, and Python won't error out. This works everywhere you can have a comma-separated list of items:

Python code:
f(a, b, c,)

def foo(a, b, c,):
    print (a, b, c,)

x = {
  "a": 1,
  "b": 2,
  "c": 3,
}

QuarkJets
Sep 8, 2008

Jewel posted:

Yeah but hardcoding poo poo is dumb and you should basically never do it??? What if you want to load the names from a webserver or don't want to have to type "<name>", every time you want to add a new name. Or have a list of names you got from somewhere that you just want to copypaste in (I know you can easily write a script to add the commas and quotes but that's not the point).

Then you replace the code in "all_names.py" with the code to load the names from a webserver, or the code to read from a text file if that's what you really want to do. My suggestion was really more related to code management. Besides, the guy was already using a "hardcoded" list of names since with an interpreted language there isn't really much difference between a list of names in a .py file that you read with an import and a list of names in a .txt file that you read with open().

QuarkJets fucked around with this message at 11:00 on Nov 29, 2013

Dren
Jan 5, 2001

Pillbug

Jewel posted:

Yeah but hardcoding poo poo is dumb and you should basically never do it??? What if you want to load the names from a webserver or don't want to have to type "<name>", every time you want to add a new name. Or have a list of names you got from somewhere that you just want to copypaste in (I know you can easily write a script to add the commas and quotes but that's not the point).

Yeah! And what if you need to decode the list from a stegonographic image payload hosted on an eBay auction? Or pull it ou of the FFT of a music file? </sarcasm>

Hard coding stuff is fine if that's all you need.

Jewel
May 2, 2009

Dren posted:

Yeah! And what if you need to decode the list from a stegonographic image payload hosted on an eBay auction? Or pull it ou of the FFT of a music file? </sarcasm>

Hard coding stuff is fine if that's all you need.

I just don't see why adding a single line of code to read a txt file is a "worse solution" than putting " ", on every name :confused:

Dren
Jan 5, 2001

Pillbug
Reading a list from a text file is fine. But depending on the use-case so is editing the python file directly.

QuarkJets
Sep 8, 2008

Jewel posted:

I just don't see why adding a single line of code to read a txt file is a "worse solution" than putting " ", on every name :confused:

Neither one is worse than the other, I was just serving it up as a suggestion to try as an alternative. I like mine better because I personally dislike using open() and mixing .txt and .py files in a project, but it doesn't really matter. What I really wanted was to see that line of code moved to its own module, since the impression that I got was that the poster was going to be using a lot of those kinds of lines in a lot of places, so putting them in all in one place and just using an import makes sense. I don't really care what the underlying code is

Dren
Jan 5, 2001

Pillbug
Anyone know how to get matplotlib on ubuntu 13.10 to properly display unicode characters?

It works on my laptop but not on my desktop. I have 13.10 installed on both.

BigRedDot
Mar 6, 2008

Dren posted:

Anyone know how to get matplotlib on ubuntu 13.10 to properly display unicode characters?

It works on my laptop but not on my desktop. I have 13.10 installed on both.

Just a guess, missing fonts?

Dren
Jan 5, 2001

Pillbug

BigRedDot posted:

Just a guess, missing fonts?

That's what I thought but I'm having a hard time telling for sure. It looks like both installs end up pointed at the same font file. Next I need to open the ttf in something and verify that the code points I need are actually in the font. Surprisingly there doesn't seem to be a *nix utility for doing that. Charmap has been in windows for years.

foutre
Sep 4, 2011

:toot: RIP ZEEZ :toot:
Semi-crossposting from the Ruby on Rails thread: I know drat near nothing about programming, but want to make a web app. A programmer friend suggested Ruby on Rails as a good starter language/framework/whatever exactly the word I ought to be using is. However, the FAQ suggests learning Python first.

Basically what I want to make is a web app that will accept forms from users with some basic info, and then spit out an automated email based on it.

Should I stick to Python for this, or would it be better to go straight to Ruby on Rails? If this is the wrong question to ask, or if a web app is the wrong thing to do for this, please let me know. Eventually I'd like to have an iOS and Android app that have similar functionality, but I figure that's a ways out.

My Rhythmic Crotch
Jan 13, 2011

I'd say give Flask a shot if you want to try python. It's easy enough to get the form submission working, and then you will possibly want to rely on some kind of email module (smtplib for example) and some kind of queue to process the outgoing emails.

Drunkenboxer
Oct 3, 2007

eh?
Hey guys, I am having some trouble with a GUI I am creating for a school project.

Basically i want to load an image into a tkinter GUI, it seems pretty simple. The image loads fine when it is loaded directly via the _ini_ function. But once inside another function it refuses to load, just a blank screen, sized to the size of the image.

Heres some code where i can reproduce the problem:

import tkinter
from tkinter import *
class ApocGUI():
def __init__(self):
self.main_window = tkinter.Tk()
self.cheat_button = tkinter.Button(self.main_window, \
#command = lambda D = PhotoImage(file = 'americasoldier.gif') : self.cheat_button.config(image = D))
command = self.clicked)
A = PhotoImage(file = 'tank.gif')
self.cheat_button['image'] = A
self.cheat_button.grid (row = 0, column = 0)
tkinter.mainloop()

def clicked(self) :
D = PhotoImage(file = 'americasoldier.gif')

self.cheat_button.config(image = D)

apoc = ApocGUI()

any help would be appreciated!

My Rhythmic Crotch
Jan 13, 2011

See this: http://stackoverflow.com/questions/4297949/image-on-a-button

In the future, please use the code tags so your code is more readable.

salisbury shake
Dec 27, 2011

foutre posted:

Semi-crossposting from the Ruby on Rails thread: I know drat near nothing about programming, but want to make a web app. A programmer friend suggested Ruby on Rails as a good starter language/framework/whatever exactly the word I ought to be using is. However, the FAQ suggests learning Python first.

Basically what I want to make is a web app that will accept forms from users with some basic info, and then spit out an automated email based on it.

Should I stick to Python for this, or would it be better to go straight to Ruby on Rails? If this is the wrong question to ask, or if a web app is the wrong thing to do for this, please let me know. Eventually I'd like to have an iOS and Android app that have similar functionality, but I figure that's a ways out.

If it's simply a web form that will post data to a server which will handle the mailing, Python + Flask or Django would be a good choice. If it's more complicated than that or you want to make it do pretty things, you'll probably have to dive into an additional language for that functionality.

iOS/Android development are different ecosystems in terms of languages and frameworks, but if you have a web app it's already cross platform ;)*

Codeacademy isn't the best resource, but this might help conceptualize what is going on and some of what you'll need to be aware of when doing Web Stuff. Relevant info for Django and relevant info for Flask. The latter is most relevant for your what you want to do, though I'm not going to pretend I read it.

edit: Flask might be a pain to set up as the docs are written for someone who is already familiar with web development in mind, but I'm sure if you ask questions in this thread you'll get pointed in the right direction.

* If you are interested, there is Xamarin that uses C# and Kivy that uses Python. The latter also suffers from that lack of good documentation, but it looks pretty.

salisbury shake fucked around with this message at 14:19 on Dec 2, 2013

Dren
Jan 5, 2001

Pillbug
plz help

http://stackoverflow.com/questions/20331189/matplotlib-unicode-not-rendering-in-ubuntu-13-10

quote:

I have an issue where the following snippet will render the unicode character as the square block you get when stuff can't render. This happens in matplotlib 1.3.1 on one of my ubuntu 13.10 systems (that was freshly installed) but the glyph will render properly on a different ubuntu 13.10 system (that was upgraded from 13.04).

I am running inside the ipython notebook, version 1.1.0. I have experienced the issue when rendering to png and to svg. My python version is the one supplied by ubuntu, 2.7.5+.

Python code:
import matplotlib.pyplot as plt
plt.plot(range(10))
ax = plt.gca()
ax.annotate(u"hello \u21c8", (1,1))
Here is a sample image.

My python environment is a virtualenv built with pip and the following requirements.txt:

code:
argparse (1.2.1)
beautifulsoup4 (4.3.2)
docopt (0.6.1)
ipython (1.1.0)
Jinja (1.2)
Jinja2 (2.7.1)
lxml (3.2.4)
MarkupSafe (0.18)
matplotlib (1.3.1)
nose (1.3.0)
numpy (1.8.0)
pandas (0.12.0)
pip (1.4.1)
pyparsing (2.0.1)
python-dateutil (2.2)
pytz (2013.8)
pyzmq (14.0.0)
requests (2.0.1)
scour (0.27)
setuptools (0.9.8)
six (1.4.1)
tornado (3.1.1)
wsgiref (0.1.2)
I have done some investigating regarding the font matplotlib is using. The following snippet,

Python code:
import matplotlib as mpl
prop = mpl.font_manager.FontProperties(
    family='sans-serif', style='normal', variant='normal',
    weight='normal', stretch='normal')
mpl.font_manager.FontManager().findfont(prop)
outputs '/home/user/projects/targets/ENV/local/lib/python2.7/site-packages/matplotlib/mpl-data/fonts/ttf/Vera.ttf'

I have looked at Vera.ttf using the ubuntu charmap utility and verified that it contains the glyphs I need. The system that correctly renders the glyphs reports that it is using the same font.

I believe this is the font matplotlib is choosing. These are the config settings related to fonts for my instance of matplotlib:

Python code:
for k, v in mpl.rcParams.iteritems():
    if k.startswith('font'):
        print '%s: %s' % (k, v)
code:
font.fantasy: ['Comic Sans MS', 'Chicago', 'Charcoal', 'ImpactWestern', 'fantasy']
font.cursive: ['Apple Chancery', 'Textile', 'Zapf Chancery', 'Sand', 'cursive']
font.serif: ['Bitstream Vera Serif', 'DejaVu Serif', 'New Century Schoolbook', 'Century Schoolbook L', 'Utopia', 'ITC Bookman', 'Bookman', 'Nimbus Roman No9 L', 'Times New Roman', 'Times', 'Palatino', 'Charter', 'serif']
font.stretch: normal
font.size: 10
font.variant: normal
font.style: normal
font.family: sans-serif
font.sans-serif: ['Bitstream Vera Sans', 'DejaVu Sans', 'Lucida Grande', 'Verdana', 'Geneva', 'Lucid', 'Arial', 'Helvetica', 'Avant Garde', 'sans-serif']
font.weight: normal
font.monospace: ['Bitstream Vera Sans Mono', 'DejaVu Sans Mono', 'Andale Mono', 'Nimbus Mono L', 'Courier New', 'Courier', 'Fixed', 'Terminal', 'monospace']
Can anyone help by providing further debugging steps I might take or possibly a solution?

Thank you.

If you know of a better place to ask for help with matplotlib than stack or on here I'd like to know about that too.

Dominoes
Sep 20, 2007

Posting again about SQlite and databases: How would I go about setting up something to replace a 3-axis nested Python data structure in the format: {symbols: {dates: {attributes: values}}}?

Create a table of the main symbols, then have a table for each symbol, with the symbol as the primary key, and attributes as columns. Each entry would be a date?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
Python code:
class Thingy():
  cached_expensive_stuff = None

  def get_expensive_stuff(self):
    if self.cached_expensive_stuff is None:
      self.cached_expensive_stuff = []
      # expensive operation to fill the array with goodies
    return self.cached_expensive_stuff
I want to be able to call get_expensive_stuff() all willy nilly...is this an alright way to go about that? Or is there a better way?

FoiledAgain
May 6, 2007

fletcher posted:

Python code:
class Thingy():
  cached_expensive_stuff = None

  def get_expensive_stuff(self):
    if self.cached_expensive_stuff is None:
      self.cached_expensive_stuff = []
      # expensive operation to fill the array with goodies
    return self.cached_expensive_stuff
I want to be able to call get_expensive_stuff() all willy nilly...is this an alright way to go about that? Or is there a better way?

You could put this in its own module and then do from thingy import cached_expensive_stuff.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

FoiledAgain posted:

You could put this in its own module and then do from thingy import cached_expensive_stuff.

My example might be a little too simplified. There's other attributes in Thingy() that are used in get_expensive_stuff, so I thought it made sense to make it a method on Thingy()

Mrs. Wynand
Nov 23, 2002

DLT 4EVA

fletcher posted:

Python code:
class Thingy():
  cached_expensive_stuff = None

  def get_expensive_stuff(self):
    if self.cached_expensive_stuff is None:
      self.cached_expensive_stuff = []
      # expensive operation to fill the array with goodies
    return self.cached_expensive_stuff
I want to be able to call get_expensive_stuff() all willy nilly...is this an alright way to go about that? Or is there a better way?

Do you mean automating caching? That's more of a ruby thing to do (:smugdog:), but there is actually a memoization decorator in Python 3's functools module (lru_cache).

What you have looks fine. Like I'd be more likely to look at it closer during code review if you had used a fancy decorator than if you just did it explicitly like you did.

Mrs. Wynand
Nov 23, 2002

DLT 4EVA
PS: make sure it's "class Thing(object):" - when you don't inherit from "object" you are defining "old style classes" which is a deprecation measure you should steer clear of.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Mr. Wynand posted:

Do you mean automating caching? That's more of a ruby thing to do (:smugdog:), but there is actually a memoization decorator in Python 3's functools module (lru_cache).

What you have looks fine. Like I'd be more likely to look at it closer during code review if you had used a fancy decorator than if you just did it explicitly like you did.

Yup, I had a feeling Python might have something fancy like that lru_cache. I'm still on 2.7 so I won't go down that route just yet. Thanks for the feedback!

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Mr. Wynand posted:

PS: make sure it's "class Thing(object):" - when you don't inherit from "object" you are defining "old style classes" which is a deprecation measure you should steer clear of.

Ah good to know. It's actually a Django model so it inherits from models.Model. I haven't actually declared any of my own classes yet outside of those models, but I will keep that in mind.

Haystack
Jan 23, 2005





fletcher posted:

Python code:
class Thingy():
  cached_expensive_stuff = None

  def get_expensive_stuff(self):
    if self.cached_expensive_stuff is None:
      self.cached_expensive_stuff = []
      # expensive operation to fill the array with goodies
    return self.cached_expensive_stuff
I want to be able to call get_expensive_stuff() all willy nilly...is this an alright way to go about that? Or is there a better way?

Lifted more or less unmolested from Pyramid's source:

Python code:
class reify(object):
    """ Use as a class method decorator.  It operates almost exactly like the
    Python @property decorator, but it puts the result of the method it
    decorates into the instance dict after the first call, effectively
    replacing the function it decorates with an instance variable.  It is, in
    Python parlance, a non-data descriptor. """
    def __init__(self, wrapped):
        self.wrapped = wrapped
        try:
            self.__doc__ = wrapped.__doc__
        except:
            pass

    def __get__(self, inst, objtype=None):
        if inst is None:
            return self
        val = self.wrapped(inst)
        setattr(inst, self.wrapped.__name__, val)
        return val
Python code:
class Thingy():
  @reify
  def expensive_stuff(self):
    expensive_stuff = []
    # expensive operation to fill the array with goodies
    print('Expensive stuff done')
    return expensive_stuff

thing = Thingy()
stuff = thing.expensive_stuff # prints 'Expensive stuff done'
same_stuff = thing.expensive_stuff # prints nothing at all

My Rhythmic Crotch
Jan 13, 2011

Dominoes posted:

Posting again about SQlite and databases: How would I go about setting up something to replace a 3-axis nested Python data structure in the format: {symbols: {dates: {attributes: values}}}?

Create a table of the main symbols, then have a table for each symbol, with the symbol as the primary key, and attributes as columns. Each entry would be a date?
I think the simplest solution would be one table to hold the symbols, then another table that has a column for date, one column for each kind of attribute, and then a foreign key to the symbol table.

Stepping up one level in complexity would be one table to hold symbols, one table to hold attribute names, and a third table would hold a foreign key to symbol, a foreign key to attribute name, have a column for the value of the attribute, and one column for the date.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

Haystack posted:

Lifted more or less unmolested from Pyramid's source

Well that's pretty drat slick, I don't quite understand everything going on in there though. What's it doing with __doc__?

breaks
May 12, 2001

Yeah, if you are comfortable with decorators this is definitely a good time to use one.

Since I was obviously late with that, edit to add: the __doc__ stuff is so that the wrapped function's docstring is retained (so you can still see it in IDEs, help(), ...). In general you should use functools.wraps to make your replacement function look like the wrapped function; they don't do so there since they are taking the pretty funky approach of replacing the wrapped function with a descriptor instead of another function.

breaks fucked around with this message at 02:48 on Dec 3, 2013

Mrs. Wynand
Nov 23, 2002

DLT 4EVA

fletcher posted:

Well that's pretty drat slick, I don't quite understand everything going on in there though. What's it doing with __doc__?


breaks posted:

Yeah, if you are comfortable with decorators this is definitely a good time to use one.

I really would discourage this. Using decorators just because you can (and ostensibly understand them) will very often lead to regrettable decisions. Some parts of python need to be used more judiciously than others. Decorators are definitely towards the "more judicious" end. Descriptors even more so.

I'm not saying you shouldn't use a memoizer here, but it is far from "definitely a good idea", and I personally would always err on the side of more explicit and obvious.

Adbot
ADBOT LOVES YOU

BigRedDot
Mar 6, 2008

Mr. Wynand posted:

I really would discourage this. Using decorators just because you can (and ostensibly understand them) will very often lead to regrettable decisions. Some parts of python need to be used more judiciously than others. Decorators are definitely towards the "more judicious" end. Descriptors even more so.

I'm not saying you shouldn't use a memoizer here, but it is far from "definitely a good idea", and I personally would always err on the side of more explicit and obvious.

Every feature of a language should be used judiciously. Python dictionaries are wonderful, but their over-allocation growth is extremely aggressive. If you don't understand this you can easily write extremely suboptimal code.

Can you expand or provide some examples for why decorators in particular are different? Right now this admonishment sounds like a "just-so" story.

BigRedDot fucked around with this message at 05:39 on Dec 3, 2013

  • Locked thread