←back to thread

317 points est | 4 comments | | HN request time: 0.629s | source
Show context
roel_v ◴[] No.17448647[source]
Having just spend the last few weeks writing Python, this comment will come off as bitter, but - really? Out of all the shitty syntax things, this sort of thing is what they're willing to fix?
replies(7): >>17448692 #>>17448695 #>>17448702 #>>17448723 #>>17448807 #>>17448862 #>>17448928 #
1. roel_v ◴[] No.17448928[source]
OK you're all right, I should've included some examples, here's just some from the last few days (I guess some of these are arguably not purely 'syntax', but to me they mostly come down to that, and I guess most can be explained away with 'different philosophy', and I'm sure someone will come out and say 'oh but if 'only' you had just done this and this', but still...) :

- Instantiating an object from a name in a string. Like instantiate a 'Foo' when you have a string variable that contains 'Foo'. I can't remember the syntax even though I looked it up two days ago, and I never will because it's such a shit show. Not to use PHP here as and example of a great language, but there at least the intuitive '$obj = new $var' works as you expect it. Or, in C++ you have to do it manually, which is also fine - at least be consistent.

- The weird sort-of typing of variables. Variables have types, but you can assign a different value of a different type to them, and the actual types usually doesn't matter except when it does. So you do print "Hey " + var but now you need to know what type var is because you might need to str() it.

- The whitespace-is-important-except-when-it-isn't. OK so braces are the devil's work, but when it's inconvenient, we're not that strict on white space (when initializing lists, when having expressions that span several lines, ...) so now everything can still look out of whack.

- .iteritems(). Really?

- super(ClassName, self).__init__(argument). Wut? Yes when I parse it token by token I understand, but why? Maybe the other magic methods are in this category too, but probably to a lesser degree.

- (I had some other things here about primitive OO capabilities, shitty package system/versioning, and some more, but those were all so far away from 'syntactic sugar' that they didn't fit this list no matter how hard I twisted the argument)

Look, I do understand why they are this way. For each of them, there is a reason that any reasonable person would say 'yeah that makes sense' to, possibly after some explanation of the history or context or whatever. But then at least be honest and stop promoting the language as so 'intuitive' or 'beginner-friendly' or 'much more clean than other languages'. Sure, it's not as bad as R, but it's still just like any other 20+ year old language in wide spread use - crufty, idiosyncratic in many respects, and in general requiring a bunch of frustrating head butting before you can be productive in it.

And to tie it to the OP - it seems this new syntax is promoted as being for 'beginners' or to make it 'easier to teach'. Well good luck with that, I say.

replies(2): >>17449255 #>>17465265 #
2. eesmith ◴[] No.17449255[source]
"Instantiating an object from a name in a string. Like instantiate a 'Foo' when you have a string variable that contains 'Foo'. I can't remember the syntax even though I looked it up two days ago, .."

Python doesn't have specific syntax for that. It can be as simple as:

  obj = globals()["Foo"]()
That assumes "Foo" is in your global namespace. If you don't care about security then you can do:

  >>> import math
  >>> s = "math.cos"
  >>> eval(s)(3)
  -0.98999249660044542
If you care about security then you might not want to allow arbitrary objects, like "os.unlink" to be referenced. There are third-party packages which provide different models of how to get objects, like Django's "import_string" at https://docs.djangoproject.com/en/2.0/ref/utils/#django.util... .

"The weird sort-of typing of variables. Variables have types,"

Variables have only one type, "reference to Python Object". An expression like 'var = "Hey " + var' may change the type of the value that var references, just like how 'var = var * 234.567' may change the type of the value that var references from an integer/long to a float, or "var = var * "Hey"', if var == 2, causes var to be a reference to the string "HeyHey".

".iteritems(). Really"

This was for a transition phase. It no longer exists in Python 3, where items() returns an iterator instead of a list.

"super(ClassName, self).__init__(argument). Wut?"

In Python 3 this is: "super().__init__(argument)", as in:

  >>> class A:
  ...   def __init__(self, s):
  ...     print("A says", s)
  ...
  >>> class B(A):
  ...   def __init__(self, t):
  ...     super().__init__(t*2)
  ...
  >>> B("hello?")
  A says hello?hello?
  <__main__.B object at 0x10b201630>
"but it's still just like any other 20+ year old language in wide spread use - crufty, idiosyncratic in many respects"

A reason for the oft-bemoaned backwards-incompatible changes to Python 3 was to remove some of the crufty, idiosyncratic language features that you rightly pointed out. You are still using Python 2.7, so cannot take advantage of those changes.

replies(1): >>17456050 #
3. roel_v ◴[] No.17456050[source]
Ok the 'global' syntax thing makes a lot more sense than the one I was told about (which involved the 'inspect' module iirc). The typing - yes I understand all of that, my point still stands that it's all 'you don't need to know all of this! Oh, at least, until you do'. Wrt python3 - fair enough, things probably do get better. But that just reinforces my point about cruft building up in any practical language, and Python being just as susceptible to it as other languages.
4. duckerude ◴[] No.17465265[source]
Referring to a class by its name is the wrong approach in Python, because classes are themselves objects.

In PHP, a class is uniquely identified by its name, everywhere. If you define a class Foo, then new $var will resolve correctly either everywhere or nowhere (the name needs to be fully qualified, to avoid namespace headaches).

That's not the case in Python. A class Foo has the same status as any other object. That means you can't rely on its name - it could be replaced by another value. But it does mean you can pass the class itself around instead of its name. Instead of putting the string 'Foo' or the literal Foo::class into a data structure or an argument list, you can just put Foo in there, and call it later.

I think the Python approach is cleaner, but then again, it's what I already knew when I first learned how PHP did it.

Python doesn't need to instantiate classes based on string values, so it doesn't provide an easy way to do that.

Python almost allowing you to take the PHP approach is a bit of a pattern. Python is dynamic enough to let you do a lot of things you shouldn't be doing. Ugly syntax like globals()[var] is usually (but not always) a sign that you're looking for the wrong kind of solution.