Hacker Newsnew | past | comments | ask | show | jobs | submit | Wickk's commentslogin

This. I work in retail and have for a while. My mother has for most of her life, and this practice is not new for the retail level of the job market.


How do you find OOP in python awkward? Out of curiosity.


Another response from a different source. Having to include self as a method argument means that those are not methods, but static functions. This really means there isn't precisely methods at all and the whole OOP part of python appears hacked together. That part seriously turned me off when I encountered it.

If there is a valid reason for this, it would go a long way in explaining away one of the major reasons I dislike python.

Edit: Appears to be a bug and I cannot respond to your post 'masklinn'. Can you rework the example to include the result as 42 being an instance variable instead? Thanks.


> Another response from a different source. Having to include self as a method argument means that those are not methods, but static functions.

This declaration makes no sense.

> This really means there isn't precisely methods at all

Of course there is:

    >>> class Foo(object):
    ...     def bar(self): return 42
    ... 
    >>> type(Foo().bar)
    <type 'instancemethod'>
    >>> m = Foo().bar
    >>> m()
    42
> If there is a valid reason for this, it would go a long way in explaining away one of the major reasons I dislike python.

I don't know (and don't really care) if you'll consider it "a valid reason", but here's GvR's reasoning: http://neopythonic.blogspot.be/2008/10/why-explicit-self-has...


Functions don't magically become methods just because the language hid the "self" or "this" parameter. You're focusing on irrelevant details.


It's not that the language is hiding self/this so much as what manually passing those as variables represent. What you are saying is that you never need to call a method like this?

> instance.method(instance)


You only have to list self in the declaration, you don't have to pass the instance to itself.

Borrowing masklinn's example:

  >>> class Foo(object):
  ...   def __init__(self):
  ...     self.n = 42
  ...   def bar(self):
  ...     return self.n
  ... 
  >>> f = Foo()
  >>> f.bar()
  42


Although you can also (and that can be rather neat when e.g. mapping or filtering) use the method as a function, if you get it from the class:

    f = Foo()
    Foo.bar(f)
note that it will typecheck the first argument to ensure it's an instance of `Foo`, it's not a function, it's an unbound method:

    >>> class Bar(object): pass
    ... 
    >>> b = Bar()
    >>> b.n = 66
    >>> Foo.bar(b)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unbound method bar() must be called with Foo instance as first argument (got Bar instance instead)


If you want to do that use the @staticmethod decorator.


Oh just, you know, create a function... There's nothing more pointless than @staticmethod, unless it was used specifically to port code it should mark whoever used it for a whipping.


> "... python appears hacked together ..."

I had to extract that as a concise summation of my subjective view of the language as a whole. (Note: hacked != bad.)


The code to call super is awkward. Instead of saying super(MyClass, self).foo(), I would rather just say super.foo().

Having to specify self or cls as the first argument of an instance or class method. This one is weird when you are learning Python because you don't pass in the first variable but it gets magically inserted for you.

Creating a class method using a method decorator. Using a decorator to do something like this seems like a hack to me.

Not having a clean way to specify what all the instance variables are outside of the constructor. People with a java background are used to putting instance variable declarations as the first thing inside a class definition. In Python, these will be static variables. This seems weird and inconsistent with the how method declarations work (methods only become class methods when a decorator is used).

BTW, I like Python.


> The code to call super is awkward. Instead of saying super(MyClass, self).foo(), I would rather just say super.foo().

That's been changed in Python 3. Although it brings other issues.

> Creating a class method using a method decorator. Using a decorator to do something like this seems like a hack to me.

Why? Even more so, why is a decorator more of a hack than adding a new keyword (java) or special-casing method declaration (ruby) itself? Note that you can also create class methods without decorators if you wish to, by using a metaclass (I believe the method won't be accessible from the instance though)

> This seems weird and inconsistent with the how method declarations work.

It's actually very coherent: every binding created in the class scope is collected and set on the class object, as if passed as the third argument to `type`. That's it. Some objects (functions) are processed a bit more, but they still end up in the same place.

> methods only become class methods when a decorator is used

That's because the decorator is basically a flag to tell the attribute-resolution process to handle this method differently from the normal method-resolution process.


Class methods needing decorators really bugs me too. The problem goes back to explicit self. The explicit self, as currently implemented, carries no information: yes, you get to pick "self" as the instance name, but everyone picks "self" for that and There's One Way To Do It in Python anyway. If you could declare a class method like this:

    class Foo(object):
      def class_method(Foo):
        pass
then suddenly explicit self gains a meaning (Hey! Instance method!) and class method declaration doesn't go through a completely unrelated mechanism.

>> methods only become class methods when a decorator is used

> That's because the decorator is basically a flag to tell the attribute-resolution process to handle this method differently from the normal method-resolution process.

Do you see how that's just special-casing method declaration in a similar way to Ruby's mechanism, just relying on the programmer to drive the mechanism himself? To a not-so-casual observer it looks like Guido wasn't willing or able to change enough semantics to make a syntactic fix work for class method declaration, despite there being an obvious space in the syntax for it to fit in, so lent on a convenient implementation detail - a hack - to get the same effect with more work for the programmer.

Of course, it's equally possible that he believes that class methods are a code smell and should be explicitly made ugly, which I could have a certain sympathy for, but to me the current situation just looks really inelegant.


> yes, you get to pick "self" as the instance name, but everyone picks "self" for that

No, actually, there have been situations in the past where using `self` was not the best choice, and I didn't. Using `self` is extremely confusing when defining methods on metaclasses for instance (self turns out to be a class object)

> If you could declare a class method like this:

You completely change the semantics of defining methods and potentially break explicit code.

> Do you see how that's just special-casing method declaration in a similar way to Ruby's mechanism, just relying on the programmer to drive the mechanism himself?

The programmer is always the driver, the difference is that decorators allow doing this without adding a pointless syntactic special case.


> No, actually, there have been situations in the past where using `self` was not the best choice, and I didn't. Using `self` is extremely confusing when defining methods on metaclasses for instance (self turns out to be a class object)

Here's somewhere that Python could have made things easier for you. What's wrong with `self` being a class object? It's something Ruby gets right, in my opinion.

> You completely change the semantics of defining methods and potentially break explicit code.

Yep. In a good way. Guido had a chance to fix this at Python 3, and didn't. Do you seriously not see the benefits of the code I posted?

> The programmer is always the driver, the difference is that decorators allow doing this without adding a pointless syntactic special case.

Yes, the programmer's always the driver, but my point is that in Python the programmer has more driving to do than necessary. The reason this is confusing and inelegant is precisely because it's not a pointless case. Decorators allow doing it, but they're absolutely not the best way, its a (ab)use of a conceptually unrelated mechanic.


I always found it weird that they use len([1,2,3]) rather than [1,2,3].len

(no, I don't want to call [0,1,3].__len__() . Why would I want to add all of those underscores.)


^ this ^ never understood why certain methods (or are they functions?) are not called on the objects. This is one of the reasons I love Ruby, everything is clearly an object.


> ^ this ^ never understood why certain methods (or are they functions?) are not called on the objects.

Because they don't depend on a given class, they're protocols. There's no "master class" in which to put them, so they go in some sort of bastardized CLOS-like generic method instead.


With duck typing, that shouldn't matter. Lots of methods in the Python standard library take "file-like objects" that have read() methods and no common superclass, and that works fine without read being a top-level function.


There's no need for a super class to have a len() method. I don't get your reasoning here, Python is not a statically typed language.



Similarly weirdly, the string join method really confuses me:

    ''.join([1, 2, 3])


That actually makes sense. Because the joining is something that a string knows how to do. Why should arbitrary lists know about string manipulation?

By the way, your example has an error, since you can't join a list of numbers. You can only join lists of strings. I.e.

    ' '.join("Hello", "World")


It seems strange at first but now it feels pretty natural. The alternatives might be to have a new global function (like len) or to have every possible iterator type have join (which sounds complicated).


In python 1.X it was a function under the string module. This is maintained in 2.x but goes away in 3.x.

string.join(['1','2','3'], ' ') == ' '.join(['1','2','3'])


It is rather arbitrary yeah, but I don't mind it. Len kind of makes sense as a function.


Not the one you replied to, but one thing that hits me as awkward is the default static behavior of variables.

something like

  class Foo:
    bar = 1
means that bar is now a static class member (static in Java's sense). It needs to be assigned to "1" explicitly in __init__ as far as I understand. That's just unintuitive and leads to lots of boilerplate, just so that you don't need specifiers like 'static'. Sometimes the fear of verbosity gets in the way of intuitiveness.


> Not the one you replied to, but one thing that hits me as awkward is the default static behavior of variables.

There's no default anything, what you wrote sets "bar = 1" on the class itself, nothing more an nothing less, just as if you'd written:

    Foo = type("Foo", (object,), {'bar': 1})
(in fact that's pretty much what the class statement is sugar for)

If you want to set it on the instance, set it on the instance.

Python's class context is a namespace like every other, you can do any computation you wish in there, and at the end the ``class`` statements collects all bindings of the namespace and sets them on the class.


Well in my case foo = Foo(); print foo.bar will print 1, so it does 'kinda' work as a default value. And that's ok, I just remembered there to be some case where it didn't behave the way I expected it to (e.g. instance member assignment overriding the content of another instance), but I wasn't able to reproduce it right now.


> Well in my case foo = Foo(); print foo.bar will print 1

Of course it will, Python's attribute-resolution (as do most languages) tries the instance, then the class, then the superclass, then... why wouldn't it work?

> I just remembered there to be some case where it didn't behave the way I expected it to (e.g. instance member assignment overriding the content of another instance)

Only two way I see for that to happen:

1. Re-setting the member on the class itself, not the instance

2. Or having the member be mutable and mutating it, since it's set on the class it's shared by all instances.


Right, of course it was the mutable use of an internal data structure.

  class Foo:
	bar = [1]

  foo1 = Foo()
  foo2 = Foo()
  foo2.bar.append(2)
  print foo1.bar
  print foo2.bar
prints [1, 2] [1, 2]

And that's the reason why I don't like that the standard way I define common instance members is an init function. Are there any decorators I could use to do that outside of any class function?


> It needs to be assigned to "1" explicitly in __init__ as far as I understand.

I don't think so. You do have to assign anything to it if you want to use it as a 'static' (actually 'class' attribute). You can access bar from Foo, as in Foo.bar or from an instance of Foo as in foo=Foo(); foo.bar.

What probably is confusing to you is if you assign a value bar in an instance then that gets assigned to the instance not the class. That is if you do foo.bar=100 then now foo instance has an object attribute called bar=100 that overrides Foo.bar=1. But Foo.bar still stays at 1.


You're right, I was mixing something up. You need mutable data structures to show the behaviour I mean, see my other comment in this tree.


EDIT: You do have to assign = You don't have to assign


All those self statements.


What's even worse IMO is the lack of a proper built-in 'super'. The self parameters at least serve the purpose of deciding whether a function is a class function or object function.

So yeah, I agree, python's OOP is kind of awkward. I love the ease of composition though, something I use extensively even in other languages since I know python.


> The self parameters at least serve the purpose of deciding whether a function is a class function or object function.

No, it does not.


It doesn't do that for the interpreter / compiler. But it's a common enough idiom that the human reader can rely on it.


To elaborate on masklinn's answer, you need to add the @classmethod decorator to get a class method instead of an instance method.


So glad I JB. Because I'm using this.


I have severe asthma, when I have an attack that will last for hours this used to be how I would describe what it's like during that time. I loathe those periods when I can't think, process a thought correctly or function like I do when I'm just breathing like normal.

I can't imagine going through this every second of my day for as long you do did. And in comparison those few hours when I can't breathe and I'm waiting for my medicine to work feel like a blessing in the sense that it could very much worse like what you experienced. Wow.


The items in question are still there, it's just the name itself that is getting formatted.

Side note: Why are the post that are giving apple the benefit of the doubt of this being a mistake getting downvoted? Really guys?


http://www.norvig.com/21-days.html

I stumbled across this incredible article reading Jeff Atwood's now-apparently-controversial post on that subject I'm avoiding like the plague.

Back to the point, it basically summarizes what I tell all of my friends who gain an interest and want to learn fast. I've been learning for over a decade out of interest now since I was 12 and I will never refer to myself as anything other than marginally competent. I akin programming to math in the sense that the ceiling is not really there because there is always more to learn and thats what the majority of your (programming) life is spent doing.


Are we talking content abuse? It's in their ToS if we are. Not entirely sure how effective they're going to be at monitoring malicious content, but it's there.


Hi, it's called filters that take 2 seconds to setup.


But then I have to click into separate folders to view the same emails which I currently take in on a single page?


I'm going to take a wild guess that a large bulk of those 8K+ emails needs to be sent straight to the trash.


Possibly 25% of them. But why? Its more time efficient to just leave them there. You seem to be missing my point :)


I just hate having unecessary cruft personally. I need to organize everything


Thought the article was going to be a question as to why. But I wholeheartedly agree as to why Python is a great forst language.

The simple fact that it's syntax light will always be the #1 reason it's a great introduction. Worry about the syntactical hangups once you have the core concepts of programming down.

I never understood those CS courses that have you diving in blind with C++


>I never understood those CS courses that have you diving in blind with C++

C++ made more sense to me than all the CS programs that were switching to Java for their intro to CS courses when I was coming up a decade ago.

C/C++ may have overhead that's confusing to a beginner out of the gate, but Java just amplifies that.


Everyone learns differently, so hey to each their own. I dabbled for years throught my HS life in php, but when it came time to actually learn I was completely put off by my first intro to CS course that used the aforementioned 'Dive head first w/ C++!' method and left the course, and was one of 18 to do so.

Started learning python on my own around age 19 and everything just skyroketed from there. I'm much more comfortable using( saying that lightly ) C++ these days but I can't imagine ever recommending it to even an enemy as their first language.

An aquaintenance on a board somewhere put it best, " C++ is like a hurricane. Gorgeous but incredibly destructive". Personally I think it all looks hideous but I get the point now.


Oh, I agree that C++ doesn't make much sense as a first language in 2012. I was just pointing out that a few years ago, the trend was toward teaching Java which is, in my opinion, even worse as a first language because you're forcing people to immediately dive into dealing with classes before they even understand what a class is.

Today, I'd agree that Python -- and possibly Ruby -- is a better first language, but when this was happening they weren't particularly mature. You just didn't have the kind of mature, syntactically-clean, object-oriented languages available that you do now. Even so, I never understood why you'd choose Java with all its excess syntax to teach a beginner.


Prob the age old reason because it's what most programmers end up using throughout their buisness life. Always been my guess anyway


Agreed. I may not be a fan of Python in general, but it is a good language for instruction for precisely that reason: less incidental complication so you can focus on inherent complexity.

As someone who’s well versed in C++, and who had to tutor CS students in it, I certainly wouldn’t recommend anyone use C++ unless they already know it and can use it effectively.


I'm one of those people who when I learn anything, I take hand written no matter what it is. I've even had language books tell me, " You probably won't need to do this" and I make sure to add it in anyway. And when that 1% time comes, my first reaction is always to the clear and detailed description that I myself wrote down. This has happened several times, ( a lot when I was getting my feet wet in server administration ). As someone who like to learn ot all no matter how out of context for the enviornment, I much prefer when stuff like this happens. I'd rather know how to do something as a just in case, then panic because I don't know something at all.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: