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
Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

huhu posted:

Simplified question.

code:
class Test:
    def method():
        print("hello")
    def method2():
        method()
How would I get Test.method2() to print "hello"?

You could change the statement in method2() to Test.method()

Better than that (but it is potentially difficult for a beginner to appreciate why), you can make method2 a class method:

code:
class Test:
    def method():
        print("hello")
    @classmethod
    def method2(cls):
        cls.method()
The main reason why you might do this is that it's more robust if you might later want to derive from Test.

Also, I haven't fixed this in my code but method() should either have a self parameter or be marked as a static method or class method (in the latter case it should have a cls parameter instead)

Adbot
ADBOT LOVES YOU

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

KernelSlanders posted:

Yup. Even if you work at Microsoft, who sits down to write a web endpoint and thinks CR LF termination is a good idea?

Wikipedia says... "Most textual Internet protocols (including HTTP, SMTP, FTP, IRC, and many others) mandate the use of ASCII CR+LF ('\r\n', 0x0D 0x0A) on the protocol level, but recommend that tolerant applications recognize lone LF ('\n', 0x0A) as well." I'm not sure whether you were downloading files rather than making web requests, but it seems to me that in that case Microsoft are quite entitled to send you CR+LF files, and if you don't account for that possibility then that's your bag.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

hooah posted:

I need a little help translating a scripta from Python 2 to Python 3, since I haven't really worked with 2. The script is from https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/multilabel/, namely trans_class.py. I know enough about the differences to clean up the print, split, and join statements, but I don't really understand what's going on in line 51 (my edit). Any help?

Looks like you need to get rid of the brackets around the lambda argument. i.e. "(num)" should be "num"

That might be all you need to do.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

KICK BAMA KICK posted:

I've never done anything more than hobbyist stuff, but I liked using abc when I was learning Python as my first language. Then when I got some experience in statically typed languages with actual interfaces, I felt like abc was just a crutch that could never really fulfill what I wanted when I tried to use it. Just my vague opinion though.

Maybe abc now interacts somehow with the new type annotations to more clearly define what's expected of an implementation? But I feel like whenever you start asking those kinds of questions, you're really asking why should you be using Python for that task in the first place?

I kind of feel like this. I had a personal project I was working on recently (still not got anywhere with it) that I started out trying to write in Python, realised after a while that I was trying to write C# in Python, switched to trying to do it in C# instead, but then got frustrated with some of the roadblocks that C# puts in your way that feel unreasonable after you've gotten used to being able to play a bit fast and loose like you can in Python*. Then I went back to Python trying to use the new type annotation stuff but it still wasn't what I was looking for.

Basically I'm in an unhappy point in between the two languages and it is pretty annoying.

* like not having a notion akin to Python's "class methods", where you have an essentially static method but it cares which class you used to call it

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Munkeymon posted:

Extension methods don't do what you want?

I don't know what you mean - I don't understand how extension methods would be relevant to this, but if you can point me to something I don't know about them that would be great.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Cingulate posted:

It's a very minor change, but 1. i/I as a variable is sometimes discouraged because it evokes imaginary numbers (don't ask me, I just see this all the time), 2. using _ makes a bit clearer we don't care about it.

I don't like this practice of using _ as a name for an "unused" variable. I think it's a bad convention. Firstly _ already means something in the standard Python interactive console, secondly it's opaque and baffling if you haven't seen it before. I prefer to use a name like "_unused" or similar. You only write it in one place after all.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Cingulate posted:

Hm ... is there a one-character option you like better?

Well, no there isn't. There's no one-character name that means "this is an unused variable the author doesn't care about" to me, although I know _ is that to some people.

Like I say, given that it's by definition something you'll type only once, there's not much need for terseness.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Asymmetrikon posted:

Python code:
class Repeat:
    def __init__(self, n):
        self.n = n
    def times(self, x):
        return [x for _ in range(self.n)]

Repeat(5).times([])

You don't get 5 different lists with this, you get 5 references to the same list.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

BigRedDot posted:

I can count the times I've used the standard interactive console _ in the last 20 years on zero fingers.

Well since you don't use it, obviously nobody does! You have opened my eyes.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Cingulate posted:

In science packages, all the time. E.g., something will do a complicated-rear end transformation and analysis on a neural time series, and I basically only want the transformed time series and one specific parameter about the transformation, but it also gives me the R^2 and the residuals and whatnot.

I don't know how these scientific packages usually work, but do these functions just return a homogeneous sequence of numbers in order to communicate the parameters back to the user? If so then really it sounds like the problem is that the interface offered by the functions is badly designed. It could and should return a result object or a dict instead. So instead of returning a list of five numbers or whatever and the user has to know what the significance of each of the 5 numbers is, it could return a dict, and the dict keys would be things like "R^2" or "r-squared" or whatever so that the return value would be self-documenting.

Compare

_unused1, _unused2, r_squared, *_unused_remaining = parameters

r_squared = parameters['r_squared']

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Cingulate posted:

Consider something like this:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.leastsq.html

Not actually what I'm using, but similar to this.

I just went and looked at that, and the documentation page didn't completely clear it up for me, but it has a link to the source code so I went and looked at that and my conclusion is that it does indeed do what I thought you had been describing. So I think it's badly designed for the reasons I gave in my previous post. Also the people designing this stuff are overly fond of coming up with unnecessarily abbreviated parameter names that are presumably clear to them but are opaque to a complete outsider like me. If I were using any of that library I'd probably put my own wrapper functions around it to give it a sane interface to my code, because it seems to me like it would be a hassle to use.

edit: They even hit on the idea of one of the return values being a dictionary with appropriately chosen keys, but they didn't make the jump to "why not just return the dictionary".

Hammerite fucked around with this message at 17:47 on Apr 10, 2016

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Cingulate posted:

I'll assume the scipy people usually know what they're doing - it's one of the biggest Python projects, and massively successful and influential - and that typically, when you see them doing something stupid, it's either because there actually is a very good reason for it, or it's a legacy thing they have to deal with being a massive project.
But the matter at hand is that this is the kind of code we are dealing with all the time, and thus, I sometimes do

code:
_, x, _, _, y, _ = overly_complicated_function(input)

The people writing SciPy may be very clever and capable or they may not be, and they may have legacy constraints or they may not, but having a user-facing function that returns a big old tuple of values with heterogeneous types or purposes, instead of a dictionary or a result object, is bad design - that's all I'll commit to. You shouldn't have to write code that looks like that to use some library.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Blinkz0rz posted:

I mentioned this up-thread but this works perfectly and encapsulates everything:
Python code:
list_of_lists = map(lambda x: [], range(k))
It's not terribly performant compared to a comprehension but this discussion is academic anyways.

But what should the name of the "x" variable be? As an expert on bikeshed colours, this is of critical importance! Critical I say!

(also needs an outer list() call, for the Python version that's good)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Munkeymon posted:

Might be me misunderstanding why classmethods are useful, but in C# if I want to make a utility method that I can just call as if it were a member of a type when it's not, I'd write an extension method. Granted, this doesn't give the extension method access to private members or anything similarly magical, but it looks like a similar use case to me.

No, that's not what I mean. I mean I wanted to have something like Python's "classmethod" where it acts like a static method (you don't need an instance to call it), but it does still care which class it's called through. A dumb, babby's- first-OOP type example would be

code:
import abc

class Animal(metaclass = abc.ABCMeta):
    @classmethod
    @abc.abstractmethod
    def noise(cls):
        return 'A noise an animal makes'

class Cat(Animal):
    @classmethod
    def noise(cls):
        return 'Meow'

class Dog(Animal):
    @classmethod
    def noise(cls):
        return 'Woof'

print(Cat.noise()) # Meow
print(Dog.noise()) # Woof
You can't do this in C#. An abstract method can't be static, and although you do have "type" objects you can't call type-specific methods on them.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

QuarkJets posted:

To be fair, it's how most languages work under-the-hood. Even just written out on paper it's a bit ambiguous

I believe that if I saw -2² written on paper I'd read it as -4 without thinking hard about it, and I'd expect to see (-2)² if it were to be evaluated the other way.

Or to put it another way, I think in written mathematics the unary minus sign is just shorthand for "0 -" and with that understood, it works with the same precedence as subtraction usually has.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

FoiledAgain posted:

Yeah, that's very unfortunate. But I'm still confused about something. I don't understand why Python reads 'ʊ̃ː' from my file in the first place, instead of reading 'ʊ~:'. Or does this have to do with the way that my IDE (PyCharm) displays stuff?

edit: I'm using Python 3.4

It might be helpful to open the file as binary (open(filename, 'rb')) and tell us what Python reports as the contents. It would be easier to work out what's actually in the file and whether your expectations for what should be displayed are based on peculiarities of how the file contents are treated by this or that program you're using.

Also, it's easy to be misled when you take the contents of the file, as text displayed by some program, and paste them on the forums, because 1) the program you're using might be doing some mangling that's hard to identify and 2) the forums might be doing some mangling, because they do that sometimes with non-ASCII characters (particularly in code blocks).

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Dominoes posted:

So to plot a function f in matplotlib, you do something like this:

Python code:
    x = np.linspace(x_min, x_max, resolution)
    y = f(x)

    plt.plot(x, y)
    plt.show()
Is there a way to automatically set x_min and x_max based on making a reasonable-looking graph?

How would it know what would result in a reasonable looking graph? I don't know matplotlib from a hole in the ground, but it sounds like it would be fairly difficult to implement something like that.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Dominoes posted:

Could be difficult and imperfect, but certainly not impossible.

No, not impossible, but a lot of effort to achieve results that the user will probably look at and decide to override with their own values anyway.

For a small set of types of functions out of a textbook (polynomials, trigonometric and hyperbolic functions, exponentials, other well-studied special functions, and sums/products/reciprocals/quotients of these various things) you could probably get good results, but it would be more work than is really justified for a minor convenience. For more exotic functions you'd be stuck, because how are you going to analyse the features of some special snowflake function and identify which bits are interesting to the user?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

BigRedDot posted:

It's fairly straightforward. You ask all the renderers to report back what their preferred bounds are (because they are the things that actually know how to account for e.g. the real radius of circles, or the extent of whatever they are drawing), and then union all them all together at the "plot" level. (That's how Bokeh implements auto-ranging, but I would expect something similar from MPL)

I was assuming that when Dominoes referred to a "function", he meant that he had a function f: ℝ → ℝ (or a reasonable variation on this, say function undefined at at most countably many points of ℝ) and he wanted to plot the graph y = f(x). That is to say, that there is no defined extent, and he wants the software to guess one.

Hammerite fucked around with this message at 15:58 on May 3, 2016

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

BigRedDot posted:

I don't understand this statement.

I'm saying, what I thought the question was is: You give the software a function, say y = f(x) = x³ + 3x + 9 or y = f(x) = sin(x) + cos(2x). The software has to guess what would be a good range of x-values to plot it over. You haven't actually calculated any values at this point.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
There's also a subclass IntEnum for if you want enums that are directly comparable to integers, so you can choose whether your enum supports the kind of "use interchangeably with integers" behaviour you get in some other languages. You also have support for the underlying type of the members being something other than integers IIRC (so if you wanted you could have an enum with strings as the underlying type).

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
Do you need to commit the transaction?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Cingulate posted:

Which one should I do? (Or: when should I do which)

code:
# 1
numbers = (100, 200, 300)

for number in some_list:
    if number in numbers:
        print("hey")

# 2
for number in some_list:
    if number in (100, 200, 300):
        print("hey")

Do #2 when the collection is only small, is used in only one place, and is not configurable.

code:
for char in s:
    if char in ("+", "-", "*", "/"):
        print("Found a maths character")
Otherwise do #1.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
What if it were

(new_remaining if dominates(candidate, other) else dominated).append(other)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Suspicious Dish posted:

You got it backwards.

Python code:
if dominates(candidate, other):
    dominated.append(other)
else:
    new_remaining.append(other)

Well I guess the fact that I hosed it up is evidence it shouldn't be used. Or at least evidence it shouldn't be used by me.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

huhu posted:

Awesome Thanks.

New Question, is there a cleaner way to write this?

[code]
columns_int = self.columns_int[:]
columns_int.remove(self.column_with_id_int)
self.columns_int_no_id = columns_int
[code]

Assuming these are lists,

self.columns_int_no_id = [col for col in self.columns_int if col != self.column_with_id_int]

(you might need to express the if-condition in some other way, depending on how exactly columns are represented and whether comparisons work on them)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
Character limits are way out of date. The only rule that should be applied is "don't take the piss".

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

jon joe posted:

Does the python len() function actually count every item in the list when it's called, or does it use some shortcut?

Objects representing a finite collection are generally supposed to adhere to a protocol whereby they define a specially-named method, __len__(), which is called by len(). That way, it is up to a given collection class to implement its own response to len(). A given collection class might cache the number of elements so that it can respond quickly when asked how big it is, or it might just laboriously count its items every time; it's up to the implementer.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Lysidas posted:

Was going to edit my post, but no point in doing that after a reply. I was going to say that implementing __hash__ as returning hash(tuple(stuff in your object)) also works with non-numeric data:

code:
>>> hash(tuple([4, 'hello', frozenset({9, 10})]))
-375596027188019708
EDIT: guess I'll edit this post too, then. I've seen people combine the hashes of non-numeric things, like

code:
    def __hash__(self):
        return hash(self.obj1) ^ hash(self.obj2)
and this is closer to what I wanted to describe as "don't do this if you can avoid it". It's rather easy to accidentally introduce some pattern in that kind of hash combination, like "hashes are always a multiple of 3" or something similar.

This Stack Overflow post discusses the use of straightforward arithmetic involving prime numbers in creating a good hashcode implementation (in C#):

http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode

It is made a bit harder perhaps by the fact that Python integers are arbitrary-precision rather than 32-bit. I don't know how hashcodes work internally in Python so I don't know how big an issue this is or how hard it is to get around it.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
The use of _ to mean "this is an unused variable" is bad. Don't tell people to do that. If you need a variable that's unused, use the word "unused".

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

No Safe Word posted:

Good lord no, _ as "ignore me" is convention. Naming a variable "unused" is worse than just naming it the intentionally-awkward-and-already-established-as-conventional name.

It's a bad convention. It's unnecessarily cryptic, and fails to be self-explanatory. On the other hand if you name a variable "unused", that's self-explanatory.

Not only these objections, but also _ is used in the Python command line interpreter to refer to the object last evaluated, so it's giving something two different meanings for no good reason.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

No Safe Word posted:

code:
>>> year, month, day, _, _, _, _, _, _ = tuple(datetime.datetime.now().utctimetuple())
>>> year, month, day, unused, unused, unused, unused, unused, unused = tuple(datetime.datetime.now().utctimetuple())
Contrived but you pick which one is better. You generally shouldn't have unused stuff at all, and the rare cases where it is used is because you need a terse way to skip it. A single, obviously-intended-to-not-be-used character, does that job more effectively than a word. And it's already internationalized to boot!

I'd use the second one but I'd put it in a helper function so I wouldn't have to look at it. I'm a bit baffled by the "internationalized" comment; are you saying you translate your program code into other languages?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Nippashish posted:

I propose we rename 'zip' to 'as_tuples_by_index' because 'zip' is unnecessarily cryptic, and fails to be self-explanatory unless you already know what it's supposed to mean.

There is some merit to this argument (unironically), but "zip" is at least a word. It doesn't do a great job of explaining what the function does though, you're right. It has always seemed to me that "transpose" or some variation on it would be a better name for zip.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Thermopyle posted:

Like...what do you gain by using the word "unused"?

As far as I can tell the only thing you gain is readability by super-new programmers at the expense of making it harder to read for everyone else.

I've dragged this argument (in which I am clearly in the minority) out for too many posts already, but... I don't see that it does make it harder to read for anybody, irrespective of their level of experience.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

No Safe Word posted:

If I see an underscore I know without any thought "oh, that's stuff that's not used". If I see anything else, I have to parse it. I also have to wonder "hmm, is it really unused? if this were just an underscore it would stand out elsewhere if somebody tried to use it, but somebody got cute and tried to use a name with semantic meaning for a throwaway variable"

So yeah, something you can immediately and without any conscious thought ignore is simpler

All of the advantageous aspects you attribute to the name "_" in this post apply equally to the name "unused", and all of the disadvantageous aspects you attribute to the name "unused" apply equally to the name "_". In your final sentence, you describe _ as "something you can ... without any conscious thought ignore", but this description applies equally to the word "unused"; if it is indeed unused then I may ignore it. The names "_" and "unused" make the same promise as to the irrelevance of the variable, assuming the reader is aware of the convention, and whichever is used it is equally easy or difficult to verify that the promise isn't broken.

Thermopyle posted:

Because there's more cognitive overhead in reading a word vs recognizing an underscore.

I disagree. There is no more cognitive overhead. However, I will recognise that whether one thing presents more, less, or same amount of cognitive overhead compared to another is down to individual perception, so what presents overhead to you may not present it to me, and vice versa.

A few times people have noted that the convention of using _ to refer to an unused variable exists in other languages than Python. This is true, and it is a bad convention in those languages too.

This will be my last post on this matter.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
I know I said I'd mute myself on this, but there is a semi-related thing that occurred to me last night.

Weren't we supposed to be able to something like this at one point, or am I imagining it:

a, *, b = [1, 2, 3, 4, 5, 6]

(so a would be 1, b would be 6, and the middle elements go unassigned)

This would be the best of all possible worlds (if you don't give a name to something, then clearly it's unused)... but it doesn't work on 3.4.2 which is what I have installed on this machine. And searching for it I get a deluge of articles/questions about function args/kwargs/unpacking, so it's a bit difficult to look up.

I could have sworn they were adding syntax like this. Of course, it doesn't handle the case where you have just one argument you want to ignore, rather than a variable number. It would be good to be able to do something like

a, ~, b, ~, c = [1, 2, 3, 4, 5]

(pulling syntax out of my rear end, but the point is it's new syntax that wouldn't previously have been valid)

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

shrike82 posted:

a, *_, b = [1, 2, 3, 4, 5, 6] works

I'm aware of that, but as I remarked, not having to give the variable a name is the best solution.

Adbot
ADBOT LOVES YOU

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Thermopyle posted:

Just look at the last edited date?

I know that and you know that, but it doesn't send out the message that the op is keeping the thread up to date (or, if it's a date far in the past, that they aren't doing so). Basically it adds confidence on the part of the reader who might not think to check the last edited date.

  • Locked thread