2
$\begingroup$

After playing around Python a little bit, I feel like Python does not encourage us to read objects's content. Take JavaScript for example: just a simple act of calling an object will list all the content of it, while in Python if an attribute is also an object, it doesn't write down that sub-object. I have to call that attribute explicitly for it to show up. If the attribute is an array of objects, it will only display the first attribute of each object in the array, not list them all.

Example:

vars(allnotes.notes[0])
{'path': WindowsPath('D:/Programming/test zone/example-vault/README.md'),
 'content': 'blabla',
 'metadata': <pyomd.metadata.NoteMetadata at 0x1b559874350>}

vars(allnotes.notes[0].metadata)
{'frontmatter': <class 'pyomd.metadata.Frontmatter'>:
 - dg_publish: True,
 'inline': <class 'pyomd.metadata.InlineMetadata'>:}

vars(allnotes.notes[0].metadata.inline)
{'metadata': {}}

I was advised to not use vars() or __dict__, just use the actual API of the classes. If an object isn't printing well without that introspection, then that's the devs fault for not writing proper string and print methods (usually via __repr__). Or in other words, Python defers the responsibility to display the objects to the dev, while JS takes that responsibility.

Are those claims correct? How do the philosophies of Python take the authors to those decisions? Why do the two languages apply different levels of encapsulation for reading data?

$\endgroup$
11
  • 1
    $\begingroup$ Whomever you talked to doesn't seem to have the first clue about Javascript. Javascript is arguably more object oriented than Python: Python for instance has no concept of object literals. Javascript also has getters, setters, private properties, non-enumerable properties, readonly properties, etc for encapsulating object state. All the stuff that person said about Python though seems to be dead on: if you have to use vars or __dict__ the class wasn't very well-designed. I'm not sure how this all ties into the actual programming language design though? $\endgroup$ Commented Sep 27, 2023 at 11:55
  • 5
    $\begingroup$ JS doesn't "take that responsibility", rather the implementation does. There is nothing in the language spec which says a JS REPL must show an object's contents. There is also nothing in the Python language spec which says that repr (or an object's __repr__ method) must be called by a Python REPL, and indeed there are Python REPLs such as Jupyter which even render some objects as interactive applets, not just the text result of repr. So this is really a question about tooling and it has very little to do with the language design or philosophy. $\endgroup$
    – kaya3
    Commented Sep 27, 2023 at 17:30
  • 3
    $\begingroup$ I think this question remains quite unclear about what it is asking. All JavaScript objects stringify to “[object Object]” by default, and even post-edit both languages have essentially the same levels of encapsulation, but it’s not clear just what “calling an object” is standing in for, and it’s hard to tell which parts of language design in these cases are relevant. I think there is a good on-topic question inside here that dials in on just one element of all of this (perhaps multiple!), but this one is still a bit scattershot and rests on the unconnected bloviations of some guy in Discord $\endgroup$
    – Michael Homer
    Commented Sep 27, 2023 at 17:53
  • 2
    $\begingroup$ @MichaelHomer I think they're talking about the difference between print(someObject) in Python and console.log(someObject) in JS. Python just prints something like <className address> by default, while JS shows the full object contents. The problem is that their analogy is wrong. "Plain" JS objects are more like Python dictionaries, which do display all the contents. $\endgroup$
    – Barmar
    Commented Sep 27, 2023 at 23:58
  • 1
    $\begingroup$ @JaredSmith True. The console in browsers is part of the debugger. Python IDEs have allow you to view details of objects in the debuggers. $\endgroup$
    – Barmar
    Commented Sep 28, 2023 at 21:10

1 Answer 1

5
$\begingroup$

TL;DR

Javascript was not at first intended to be a general purpose programming language, Python was.

Longer Answer

Javascript was developed in 1995 to add small amounts of behavior to web pages that at the time were almost entirely static documents. Pages with no JS were common, pages with a couple of inline scripts < 20 lines were about it. As Eric Lippert, a user here who worked on the Microsoft implementation has said it was just there to "make the monkey dance when you move the mouse".

So until about 15-20 years ago Javascript worked pretty much the way your conversation partner said: what's that? You want encapsulation of object internals in your < 100 LoC JS? Why?

But then a funny thing happened, people started using it more and more, and for ever more ambitious purposes. Then Microsoft invented the XmlHttpRequest object (2001) that allowed pages to communicate with the server in the background, and the world was never the same. By about 2005 it was available in most major browsers, and we had apps like gmail to show just what was possible with it.

Well, once people started writing real programs with Javascript, it became clear pretty quickly oh wait, we do actually need proper language features like private properties, encapsulation of internals, etc.

So people added them. Either in an ad hoc fashion (e.g. using closures for encapsulation), or increasingly to the language itself. Javascript has arguably had feature parity with the things that your conversation partner mentioned about Python since about 2015 (note that's almost 10 years now). So that person's information about JS is quite a bit out of date.

But in terms of language design, the designer(s) of Javascript didn't include those features earlier on because why bother, but once it was clear those features were necessary they added them for the same reasons Python has them.

But I see stuff when I console.log!!!

Yeah, about that. You see, the behavior of the console here is explicitly implementation-defined in the standard. So console.log is pure magic: it need not be bound by the semantics of Javascript and can and does sometimes expose internals like [[Call]] or [[Construct]] that are not actually exposed to the Javascript programmer at all. So don't be surprised if you see private properties or the entire prototype chain or even inaccessible internals when you console.log an object.

Contrast this with the behavior of print in the reference implementation of Python: it very clearly spells out that objects get run through the str function which calls the object's __str__ magic method if present and delegates to repr if one is not found.

However it's worth noting here that Python (as far as I know) does not actually have a formal standard, and the behavior of the CPython reference implementation is not binding on alternative implementations, although I've never used it I would not be at all surprised if e.g. Jython did something quite different.

$\endgroup$
7
  • $\begingroup$ so is it correct to say that it's not Python who does not encourage us to read objects' content, but it's JS who didn't bother to apply the standard of encapsulation at the first place? If so, then why does that standard become standard? It's likely that I'm wrong, but in my understanding as long as I can get the data of the sub-objects they are not really hidden to me. The language only discourages me to read it, but doesn't actually hide them. Also, if JS has caught up the standard, then why I can still read the data easily? $\endgroup$
    – Ooker
    Commented Sep 27, 2023 at 12:27
  • 1
    $\begingroup$ @Ooker "as long as I can get the data of the sub-objects they are not really hidden to me" modern JS is better at this than Python: JS has true private properties prefixed with # whereas obj._ClassName__property will still let you get at obj's "private" __property in Python. So the correct formulation is "Python discourages reading private data, Javascript disallows it". "If JS has caught up the standard, then why I can still read the data easily" because you wrote it that way? If you use a private property with # then you can't read it at all, full-stop. $\endgroup$ Commented Sep 27, 2023 at 12:33
  • $\begingroup$ See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… $\endgroup$ Commented Sep 27, 2023 at 12:37
  • $\begingroup$ And just to be clear, I'm not trying to bash Python here, it's a solid language and IMO a better one over all than JS (which doesn't even have a standard library in Year of Our Lord 2023 because reasons). But whoever you were talking to was clearly just parroting some nonsense JS hate likely out of overzealous techno-religiosity. $\endgroup$ Commented Sep 27, 2023 at 12:42
  • 1
    $\begingroup$ @JaredSmith: You say "However it's worth noting here that Python (as far as I know) does not actually have a formal standard". It has a formal standard, it's what you get on the language docs (specifically the Language Reference and Library Reference). It does mix with the CPython reference interpreter's documentation, with things specific to CPython called out as implementation notes, but PyPy, Jython, IronPython, etc. are all following those reference documents as an implementation guide. $\endgroup$ Commented Oct 17, 2023 at 23:32

Not the answer you're looking for? Browse other questions tagged .