Godot: Private variables or functions in GDScript

Created on 25 Apr 2018  ·  47Comments  ·  Source: godotengine/godot

Issue description:
It can be matter for better code structure, if some variables and functions can be not available from other scripts and be local to specific script. Maybe introducing new keyword for this ? Or I something miss and its possible right now ?

archived discussion feature proposal gdscript

Most helpful comment

I know this is closed and archived already (not sure if there should be another issue opened for this), but access modifiers is a pretty important feature in any programming language. If I want to create a new Node addon for Godot and my new node has internal state variables that should not be modified outside of the Node, there's nothing preventing that from happening. I understand that you can use leading underscores to mimic this feature, but it still does not prevent access which is the whole point of access modifiers. In my opinion this is a pretty big deal as there is no way to control the way in which others interact with your objects.

All 47 comments

The closest thing for variables is to use setget to lead to a function that either does nothing or prints a warning. But no, no true private variables or functions.

@YeldhamDev Sadly, setget is helpful but if you dont want to see a public property - there is no way to do this. Thats bad, @reduz what do you think ?

It's not possible in Python either: even the double leading underscore doesn't prevent you from accessing and modifying variables. In Python you use conventions instead: one leading underscore to indicate a variable is private, ALL_CAPS to indicate something is a constant... they're still accessible from anywhere but in practice it's not an issue.

@NathanLovato Maybe GDScript should differ from Python in that case ?

@Chaosus You should provide arguments to explain why private variables are necessary. Otherwise it's unlikely someone will get to work on this.

Private variables are here to help encapsulate data and prevent coupling with other classes - it prevents other classes from accessing these variables. If you don't access them in the first place the problem is solved as well.

In both cases - using the private keyword or writing using a convention - you have to learn when and how to make variables private, when and how you should be able to access them. You have to learn to design your classes so that you can change the internals later without breaking their interface and vice-versa. I think that's your biggest source of trouble when it comes to code architecture.

Regarding Python, it works for millions of Python developers. There is a mechanism to make variables "private", that prevents direct access, and it's simple: write two leading underscores instead of one. But I've yet to see someone use it. It's not been available in JS until recently either. There are probably other languages like that.

I'm not saying it shouldn't be in GDscript - I really don't mind if other people have a good use for the feature. I'm just not convinced it's that useful. E.g. Godot could just not list variables with a leading _ or two in autocompletion (although it does use _function_name as a convention for virtual functions) ?

I just dont wanna see an internal methods with intellisense in GDScript, and make it more like C# and other statical typed languages

Yeah, I agree its difficult to implement and requires new keyword, too much effort for very tiny result
The solution with "__" prefix is partially solves the problem, thanks, (I never worked with Python so its something new to me).

I know this is closed and archived already (not sure if there should be another issue opened for this), but access modifiers is a pretty important feature in any programming language. If I want to create a new Node addon for Godot and my new node has internal state variables that should not be modified outside of the Node, there's nothing preventing that from happening. I understand that you can use leading underscores to mimic this feature, but it still does not prevent access which is the whole point of access modifiers. In my opinion this is a pretty big deal as there is no way to control the way in which others interact with your objects.

Yeah I agree with @dylmeadows it would be useful in this way

I am definitely pro private functions and variables as well.

  1. Yes, we do have a convention for private using a _ in front of a methods name BUT the very same convention is used for virtual functions. So if I see an underscore it could mean either "do by no means touch that function!" or "overwrite that function!". That's hella dangerous, honestly.

  2. If I am working alone or in a very small team on a small project, it doesn't weight in too much because I know what functions are meant to be used and what functions are for internal usage only.
    But with growing teams, this gets more and more difficult. People work with classes they didn't write themselves all the time and I since I am a person who writes a lot of small internal functions to make things work I really want to be able to prevent people to call these functions, because if they use those it might lead to unintentional behavior and bugs and it costs time to fix these things once mistakes are done. And despite a common convention, these things will be happening in a larger team, because they after all are callable from outside.

  3. Last but not least; auto completion. I am someone who use this a lot to learn what a class can do.
    I just put that '.' at the end and see what functions pop up. If something sounds useful, I use it.
    It would be much cleaner if it wouldn't be cluttered with all those functions that are not supposed to be called anyways. Besides - and again - i still don't know whether these _name functions are private or virtual.

Also, private variables can even be useful on a personal project. There are sometimes periods of time I cannot work on the game that I am working on, so I start forgetting what some of my functions do. Or, I forget which ones I should and should not use.

Private variables would be great with this! It would make sure that a variable or function cannot be accessed outside of a Node, and when I come back to a project I could guess how to use a variable and not have to read through all of my code completely again.

I second what Byteron and dylmeadows said as well. They just wrote their posts well enough and said exactly what I was thinking. Just wanted to add my two cents.

I'll reopen as several users are interested and want to discuss this. It's still not planned, but we can discuss and see if there's a strong interest in the community.

Python isn't the best language mentioning as ideal.
It has been stated that Godot is very object-oriented. Every script is an object as well. One of the main principles of object oriented programming is providing encapsulation. if I want to have something untouched from outside, it's probably for the best reasons.

I've personally never encountered a time where I absolutely needed to prevent people from editing variables or accessing a function. Any time where I would want to tell people not to mess with something unless they know what they're doing, I prefix its name with an _ (or _internal_ or similar).

I would not object to a keyword (or similar) that would simply hide the variable/function from auto-completion. I just don't think preventing access entirely is needed.

On the one hand, it is better to warn, not to forbid. But on the other hand, private fields and methods are usually used many times. And long variable names (e.g. _internal_variable) are a bit annoying.
In any case, the presence of the keyword private does not force you to use it.

Private members of the class to something like constants. Similarly, we can write the variable name in BIG LETTERS and agree that we will not change its value. But we don't do that, do we? That is, private variables are a cross between ordinary variables and constants. Why not enter a special keyword for this case?

Yes, we do have a convention for private using a _ in front of a methods name BUT the very same convention is used for virtual functions. So if I see an underscore it could mean either "do by no means touch that function!" or "overwrite that function!". That's hella dangerous, honestly.

That's the biggest issue I see here. Instead of private keyword, maybe we could have a virtual keyword? Some virtual methods already appear in autocompletion when you write "func", so a keyword to explicitly differentiate between virtual functions you are supposed to overwrite and private functions that shouldn't appear in autocomplete could be enough. The benefit of virtual keyword is that you'd use it less often than private, so it's less writing.

I would be happy to see private class members included as well. There is a reason this exists in other languages. Other consumers/team members (or even yourself) do not need to know how every class works. In fact, they perhaps shouldn't even have the option to fool around with functionality thats supposed to be internal anyways.

I understand that the leading underscore should "indicate" that this is a private member, but in practice no one cares if somehow modifying it gets the job done. This is especially painful if you want to use some of it as a plugin and everyone can just change whatever they want. I would like to have full control over the state of any object/script I create. Having objects that can change any aspect of their state whenever someone pleases to do so makes producing code that others can consume more than irritating.

Besides all that it would be great to declutter the list of "available" variables/functions.

Can I make one recomendation to the Dev team then please considering all this? Change Autocomplete list order. Any var or func that does not start with a letter or number appears at the __Bottom__ of the auto complete list. Then you pretty much have to type _ to see the item¿ Additionally it would be nice if we could use other non-maths or logic symbols in names? Not tried it yet but would €Display or ¥Print be acceptable function names? Etc.

Additionally it would be nice if we could use other non-maths or logic symbols in names? Not tried it yet but would €Display or ¥Print be acceptable function names? Etc.

See https://github.com/godotengine/godot/issues/24785.

So, After tinkering around with this I came to the conclusion that if you define a setter that does nothing, even if you try to assign a new value to that same variables in a different script and try to print it, the original value will be printed. It's not really private, but I guess it's close enough...

meaning that there is no hint whatsoever that the variable that appears to be public and you just modified was not changed?
well have fun debugging code that use this method extensively.

Instead of empty setter, you can also print an error.

I still only know that I've done something I shouldn't have once I fire up the program and actually hit that line of code. It still appears to be public while writing code and it still requires multiple lines of code to set up a single private variable.
Putting a private in front of that variable is way shorter, doesn't require any additional lines of code and would stop me from falsely accessing them right when I typing it.

GDScript feels quite C++-ish to me despite the fact that it's a dynamic language. When I switch from writing code in C++ to GDScript I miss those access modifiers. That being said, GDScript is missing full support for OOP indeed.

I only skimmed through this issue, but it would be nice to at least be able to hide functions and variables from autocomplete if their names are prefixed with an underscore. I guess the prominent issue with that is determining whether it's a virtual function and therefore probably should appear regardless

Thing is that the underscore is also used for virtual functions, and there certainly are cases where you want virtual functions be public too.

Maybe hide underscore-prefixed functions from other nodes/object only, but show them for calls on self/base.

My suggestion would be to use single underscore for virtual functions and double leading underscore for "private" functions. This way we can hide them from the autocompletion without affecting the virtual functions.

Using underscores to hide a variable is bad because when you change access _attribute_ of the variable, you have to change its _name_. In fact, variable and _variable are different names.
This is also like a dot in UNIX file names: quite a controversial decision.

Here's my opinion

  • Prefix with "__" for private functions
  • Functions with "__" don't appear in autocomplete
  • "private func x()" is syntactic sugar for "func __x()"

The above breaks any code that includes a variable prefixed with "__". But, excluding that, I think that system would be ideal.

GDScript's features thusfar are very similar to Python/JS, and both of these languages don't have private variables and functions for very good reason - it's a complete antithesis of their design philosophy. You have the freedom, and that freedom is important, it's what makes it easy to code. You sacrifice encapsulation, but that's their philosophy. True encapsulation is already broken without typechecking [Unless you check all the types yourself, which you're likely not going to do]. So, unless they implement strict typing, private variables feels wrong. In the gradient of OOP, strict typing comes before private variables. There are many languages with strict typing but no private variables, but I don't know of any languages with private variables and no strict typing. This is again, for good reason. Beyond that, JS even gives you access to the entire inheritance tree and lets you change those aspects too. You can change what class an object inherits from during runtime, by any piece of code that has your object! Of course, that doesn't happen, but shows the design philosophy.

So, in my opinion, true private variables would drastically hinder the language. Anyway, I think Python's system does it well, you have __ that you can use to access the private variables, but it makes it clear you're messing with something internal, and yet it doesn't meaningfully restrict you. Anyone who wants a true OOP design philosophy can simply never use "__", or have it in their company's or project's coding style. Maybe an option to mark it as an error would be nice. I mean in general duck typing and private variables don't really go together. At minimum you totally screw up the namespace because now what, obj.set("hi", 5) doesn't work if "hi" is private? But it does work if "hi" doesn't exist? That doesn't make much sense... So, a very strong no for forcing private to be completely inaccessible no matter what you do, that is my vote. Very strong yes for private variables to exist the way Python currently does it. Tbh I'm still not sure how to resolving the duck typing issue with private variables anyway, even if the desire was to have truly and inaccessible private variables. I guess you just block obj.set and make it throw an error. Now obj.set needs to return a boolean it seems, which is weird. An is_private call? That you have to call before each use of obj.set? idk

[Oh my god through for real can we get actual error detection, we're talking about private variables but as of right now if you have a bug in gdscript the game will just silently ignore it (facepalm). Maybe I'm doing it wrong but if any my code does something illegal gdscript seems to just return null from the function, which makes it so hard to track down, JS has ever been that bad and JS is a mess of a language. I know crashing the game might be too much but I keep having to just binary search my codebase by putting print statements until I find two consecutive print statements where the former prints and the latter doesn't, just to figure out where the code broke. JS/Python are surprisingly much stricter in that sense, despite how free they are in everything else.]

I suggest to find a consistent project organization to minimize the problem. You can use the root node of a scene as the interface to control the scene from outside and a child script as a backend.

Alternatively you can use only methods, export vars, and signals, and never touch to the simple variables from outside. That's a simple convention and GDScript can keep its simplicity.

It's not possible in Python either: even the double leading underscore doesn't prevent you from accessing and modifying variables. In Python you use conventions instead: one leading underscore to indicate a variable is private, ALL_CAPS to indicate something is a constant... they're still accessible from anywhere but in practice it's not an issue.

I just want to say, that it is possible to have _private_ attribute in Python.

Quote (https://www.python.org/dev/peps/pep-0008/):

__double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

__double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented

If you click that link and CTRL+F "private" you'll get

We don't use the term "private" here, since no attribute is really private in Python (without a generally unnecessary amount of work).

Double underscore or single underscore variables act just like normal variables, it's just a convention to reference that they shouldn't be used and may change when you update a library because they're internal. In general, since pythonic languages like GDScript treat objects as if they're just dictionaries, it would be awkward to try to force private variables and have them consume the namespace.

If you click that link and CTRL+F "private" you'll get

We don't use the term "private" here, since no attribute is really private in Python (without a generally unnecessary amount of work).

Double underscore or single underscore variables act just like normal variables, it's just a convention to reference that they shouldn't be used and may change when you update a library because they're internal. In general, since pythonic languages like GDScript treat objects as if they're just dictionaries, it would be awkward to try to force private variables and have them consume the namespace.

I agree, they don't call it _private_ attribute. However let me describes how it works:

# defining class Employee
class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.__salary = salary
>>> emp = Employee("Bill", 10000)
>>> emp.__salary
# AttributeError: 'employee' object has no attribute '__salary'

So it is not called a _private_ attribute, but it behaves almost like it.
It would be great to have an almost private attribute in GDScript as it exists in Python.

Oh yes, I strongly agree with you. Python is simply giving you syntactic sugar for using ._Employee__salary. I personally don't like the way python does it and I think it can be strongly improved in Godot, as I mentioned in my comment,

class Employee:
      var name # normal
      private var salary # Syntactic sugar for var _salary

Which is cleaner because _Employee__salary is an ugly way to hide the variable name, and having a private keyword makes it just like normal OOP. Even better, this blocks the ability to have a public variable salary and a private variable _salary, which would be ugly and should desirably be a syntax error just like it is in Java. This is because both would be declared "var salary" and "private var salary", a clear conflict. Another way to think about would be "In order to access the private variable of some other class C with member m, you have to use an underscore as in C._m". We could then make it an error to declare a variable beginning with an underscore, ie to make private the only way to declare it, so that it's clear what is being done.

I think the only reason why python has the less than desirable situation it does rn is because there's no declarations at the top for the variables, you just make up the class variables in any of the function bodies. GDScript seems to require declarations in the class body, giving it an easy segue into Java-like private declarations.

I'm not fond of having keywords that act as syntax sugar unless they save a lot of typing. Here, typing out private will actually make you write more characters, which makes it an anti-shortcut :slightly_smiling_face:

Also, what about methods? Several virtual methods start with an underscore, so we can't use a single underscore to mark them as private. We could use two underscores though, which would avoid conflicts at the expense of being longer. I also like the idea of following Python conventions when it makes sense – the "dunder" has been popular for a while in that language.

I don't think the intent is for it to be viewed as a shortcut, instead the idea is that outside of the class, you use "_" to access private variables. The syntax sugar would be how its implemented. Essentially identically to how python does it. But like yeah it's true, in python's case it the syntax sugar saves a lot of typing, but thats only because it aliases into something stupid long. Aliasing into something shorter is just strictly better, so having a shorter alias and then choosing to not have that syntax sugar because the alias is too short, just boils down to whether or not we should support private variables at all; we don't have to, we can just have users prepend variables with underscores or pick their own convention. It's just for the Java and C++ minded folks, who would rather write "private var myvariable" as opposed to just taking "_myvariable" as private as a convention, which feels weird when coming from an OOP world, even if they both accomplish the exact same thing. Double underscore would match Python's syntax quite well, so I'm up for that one as well, esp if _ conflicts with other stuff

I'd much rather have a keyword that explicitly defines the behavior outside of what can be misinterpreted as only style conventions. private gets my vote.

Adding fire to the discussion: the python styling convention for "private" members is to add an underscore before the name, which is _already_ used by gdscript for a different purpose in common event methods like _ready(), _input, and _physics_process, to name a few. Are those supposed to be private? How would adding a private keyword interact with these methods? Would other keywords like protected also need to be implemented?

In any case, I'm all for enforcing restrictive directives _by design_ rather than just letting users define conventions. But I'm not so sure private class members would give the intended improvement given the complexity of implementation. The entire API would have to be revisited too, I imagine. The whole language would have a completely different paradigm.

Yeah, someone already noted that. (See Calinou's response) Double underscore would be the way to go. Same as Python as well.

My 2c. In Python nothing prevents anybody to access class members that start with _, and with some internal knowledge with __ either.

It is all about showing intent. The philosophy is that we are all adults, we can make the decision whether we really need to access supposedly private variables or functions. And if we do do that, we are on our own to deal with the consequences.

@sanchopanca

  1. GDScript is not Python.
  2. Following your logic, constants are also not needed (var CONSTANT = 1).
  3. Not everyone likes to use __.

I am for the private keyword, it won't even break compatibility.
Instead, making func and var private by using _, would change things for a few using it for other reasons (I use _ only in function's parameters).

It reminds me of the new static typing feature and this private and virtual feature would go the same way.
It would provide a clearer code base, with better error detection, better autocompletion and also auto-documentation of the code.
If someone reads your code, they would understand better what it does.

I'm wondering how hard implementing two new keywords would be for the dev team.
It would be far easier than a typing system for sure and would provide a lot of value.
If someone of the dev team could give me pointers on what to do, I would be happy to help to be honest!

Just to add one more vote for adding private and protected keywords.
If you ever wrote code that some other developer is going to use, you can't be against that.
All against adding a keyword can check this topic:
https://softwareengineering.stackexchange.com/questions/143736/why-do-we-need-private-variables

We are still going to use GDscript but why not make it better in the process.

_, __, ___, and so on is plain stupid as much as adding prefixes to variable names to suggest types
intAge, strName, bIsAlive... all of these only show missing language features.
So even without comparing GDScript to Python or other languages, the dev can run a poll to see do majority want or don't want these two keywords ;)

If the feature is implemented, I hope the C++ way will be chosen. The "private" or "public" keyword in front of every declaration make C# cumbersome for reading.

I personnally wouldn't like the C++ way, since we don't have the C++ typing syntax and everything would be public by default. i'ld value being able to set a variable to private without adding another line -or moving it to a new line- more than not seeing the private keyword a lot.

private var foo : String = "foobar" is more in line with the usage of the existing export and onready keywords, too.

Closing in favor of https://github.com/godotengine/godot-proposals/issues/641, as feature proposals are now tracked in the Godot proposals repository.

Was this page helpful?
0 / 5 - 0 ratings