Declaring a variable in a class (outside of a function): all class functions can access it (basically a public variable)
Declaring a variable inside a function inside a class: only that function can access it (it's in that function's scope)
Declaring a variable with self.(variable name) inside a function inside a class: all class functions can access it (how is this different from global (variable name)?)
And since there is no private/protected, everything is public, so everything accessible from inside a class is accessible from outside the class.
Are there any other nuances I should know, or have I pretty much got it?
Since the listing in your question is not 100% clear, I've decided to explain it with a simple example. It also includes some things like __something variables you did not mention in your list.
class Test:
a = None
b = None
def __init__(self, a):
print self.a
self.a = a
self._x = 123
self.__y = 123
b = 'meow'
At the beginning, a and b are only variables defined for the class itself - accessible via Test.a and Test.b and not specific to any instance.
When creating an instance of that class (which results in __init__ being executed):
print self.a doesn't find an instance variable and thus returns the class variable
self.a = a: a new instance variable a is created. This shadows the class variable so self.a will now reference the instance variable; to access the class variable you now have to use Test.a
The assignment to self._x creates a new instance variable. It's considered "not part of the public API" (aka protected) but technically it has no different behaviour.
The assignment to self.__y creates a new instance variable named _Test__y, i.e. its name is mangled so unless you use the mangled name it cannot be accessed from outside the class. This could be used for "private" variables.
The assignment to b creates a local variable. It is not available from anywhere but the __init__ function as it's not saved in the instance, class or global scope.
Declaring a variable at the top level of the class is like declaring a static or class variable. Qualifying it with self is declaring an instance variable. Class variables can be modified by referring to them by class name (e.g. Class.x = 5) and all instances will inherit these changes. Instance variables are private to an instance and can only be modified by that instance.
You can achieve some level of access control using underscores. See private variables in the Python tutorial. By convention, variables starting with one underscore, e.g. _foo are non-public parts of an API, and names starting with two underscores e.g. __foo will have it's name mangled to be _classname__foo.
Although answered, let me add some comments to your questions:
Declaring a variable in a class (outside of a function) : all class functions can access it (basically a public variable)
This is like a static variable and can be called using the class name. These variables are available to all functions, any functions can modify it and print it.
Declaring a variable inside a function inside a class : only that function can access it (it's in that function's scope):
If the variable is declared without self then it is accessible within that function only, like a local variable. However, if it was declared using self like self.var= 'somevalue', then it is accessible via any object but not via the class name.
Declaring a variable with self.(variable name) inside a function inside a class : all class functions can access it (how is this different from global (variable name)?)
See answer in the above part.
And since there is no private / protected, everything is public, so everything accessible from inside a class is accessible from outside the class
Yes, but we can use single underscore to tell the world this variable is private, but technically that actually doesn't make it private.
we can use the scope in this for as :
case 1: In the Class
class test:
def __init__(self, a):
self.__elements = a
def change_a(self): self.__elements = 5
case 2 : Outside class
t = test(5)
This will access by as object._classname__privatevaribalename
print(t._test__elements)
this will print the change value of a
Related
class Channel(object)
channel_mapping = {
'a': 001,
'b': 002,
'c': 003
}
def __init__(self):
...
def process(self, input):
channels = input.split(',')
for channel in channels:
if channel in self.channel_mapping:
channel = self.channel_mapping[channel]
break
...
I defined channel_mapping as class variable, and why do I need to use self to refer to it? I thought I should just use channel_mapping or cls.channel_mapping in the process() function.
Also, to define channel_mapping as a class variable like this, or define it as an instance variable in the initializer, is there any thread safety concern in either case?
I defined 'channel_mapping' as class variable, and why do I need to
use 'self' to refer to it?
You can refer class variable via self (if you ensure it's read-only) and cls inside the class and it's methods and via classes object or instances from outside of the class.
What is the difference between using cls and self? cls is being used in classmethods since they doesn't require initialization and so instance of the object, and self is used inside the methods which do require instances of the object.
I thought I should just use
'channel_mapping'
Scopes inside python doesn't work as in C# for example, where you can call class variable by just writing it's name omitting this where it's redundant. In Python you have to use self to refer to the instance's variable. Same goes to the class variables but with cls (or self) instead.
If you are referencing channel_mapping you are just referencing a variable from the current or a global scopes whether it exists or not and not from the class or it's instance.
or cls.channel_mapping in the 'process' function?
From the class methods you would want for sure to use cls.channel_mapping since cls represents class object. But from the instance's methods, where instead of cls you have self you can refer to the class variable using self.__class__.channel_mapping. What it does is simply returning instance's class which is equal to cls, and calls class variable channel_mapping afterwards.
self.channel_mapping though would return the same result but just because in your code there are no instance attribute called channel_mapping and so python can resolve your reference to the class variable. But if there would be channel_mapping variable inside the instance it won't be any longer related to the original class variables, so in that case you would want to keep channel_mapping read-only.
Summarise, to refer class variable from the class method you would want to just use a cls and to refer class variable from the instance method you better use self.__class__.var construction instead of self.var one.
Also, to define 'channel_mapping' as a class variable like this, or define it as an instance variable in the initializer, is there any thread safety concern in either case?
There are situations when you want to change variables in all instances simultaneously, and that's when class variables comes in handy, you won't need to update every responsible instance variable in every instance, you will just update class variable and that's it.
But speaking of thread safety I'm not really sure will it be simultaneously updated in every thread or not, but self.__class__ will return updated version of a class a soon as it will be updated, so self.__class__ variables will be up to date every time you call it minimizing period within which different threads will use different values of the same variable.
Going up with the initialized variable though, will take longer to update if there are more than one instance so i would consider it less threadsafe.
Declaring a variable in a class (outside of a function): all class functions can access it (basically a public variable)
Declaring a variable inside a function inside a class: only that function can access it (it's in that function's scope)
Declaring a variable with self.(variable name) inside a function inside a class: all class functions can access it (how is this different from global (variable name)?)
And since there is no private/protected, everything is public, so everything accessible from inside a class is accessible from outside the class.
Are there any other nuances I should know, or have I pretty much got it?
Since the listing in your question is not 100% clear, I've decided to explain it with a simple example. It also includes some things like __something variables you did not mention in your list.
class Test:
a = None
b = None
def __init__(self, a):
print self.a
self.a = a
self._x = 123
self.__y = 123
b = 'meow'
At the beginning, a and b are only variables defined for the class itself - accessible via Test.a and Test.b and not specific to any instance.
When creating an instance of that class (which results in __init__ being executed):
print self.a doesn't find an instance variable and thus returns the class variable
self.a = a: a new instance variable a is created. This shadows the class variable so self.a will now reference the instance variable; to access the class variable you now have to use Test.a
The assignment to self._x creates a new instance variable. It's considered "not part of the public API" (aka protected) but technically it has no different behaviour.
The assignment to self.__y creates a new instance variable named _Test__y, i.e. its name is mangled so unless you use the mangled name it cannot be accessed from outside the class. This could be used for "private" variables.
The assignment to b creates a local variable. It is not available from anywhere but the __init__ function as it's not saved in the instance, class or global scope.
Declaring a variable at the top level of the class is like declaring a static or class variable. Qualifying it with self is declaring an instance variable. Class variables can be modified by referring to them by class name (e.g. Class.x = 5) and all instances will inherit these changes. Instance variables are private to an instance and can only be modified by that instance.
You can achieve some level of access control using underscores. See private variables in the Python tutorial. By convention, variables starting with one underscore, e.g. _foo are non-public parts of an API, and names starting with two underscores e.g. __foo will have it's name mangled to be _classname__foo.
Although answered, let me add some comments to your questions:
Declaring a variable in a class (outside of a function) : all class functions can access it (basically a public variable)
This is like a static variable and can be called using the class name. These variables are available to all functions, any functions can modify it and print it.
Declaring a variable inside a function inside a class : only that function can access it (it's in that function's scope):
If the variable is declared without self then it is accessible within that function only, like a local variable. However, if it was declared using self like self.var= 'somevalue', then it is accessible via any object but not via the class name.
Declaring a variable with self.(variable name) inside a function inside a class : all class functions can access it (how is this different from global (variable name)?)
See answer in the above part.
And since there is no private / protected, everything is public, so everything accessible from inside a class is accessible from outside the class
Yes, but we can use single underscore to tell the world this variable is private, but technically that actually doesn't make it private.
we can use the scope in this for as :
case 1: In the Class
class test:
def __init__(self, a):
self.__elements = a
def change_a(self): self.__elements = 5
case 2 : Outside class
t = test(5)
This will access by as object._classname__privatevaribalename
print(t._test__elements)
this will print the change value of a
Declaring a variable in a class (outside of a function): all class functions can access it (basically a public variable)
Declaring a variable inside a function inside a class: only that function can access it (it's in that function's scope)
Declaring a variable with self.(variable name) inside a function inside a class: all class functions can access it (how is this different from global (variable name)?)
And since there is no private/protected, everything is public, so everything accessible from inside a class is accessible from outside the class.
Are there any other nuances I should know, or have I pretty much got it?
Since the listing in your question is not 100% clear, I've decided to explain it with a simple example. It also includes some things like __something variables you did not mention in your list.
class Test:
a = None
b = None
def __init__(self, a):
print self.a
self.a = a
self._x = 123
self.__y = 123
b = 'meow'
At the beginning, a and b are only variables defined for the class itself - accessible via Test.a and Test.b and not specific to any instance.
When creating an instance of that class (which results in __init__ being executed):
print self.a doesn't find an instance variable and thus returns the class variable
self.a = a: a new instance variable a is created. This shadows the class variable so self.a will now reference the instance variable; to access the class variable you now have to use Test.a
The assignment to self._x creates a new instance variable. It's considered "not part of the public API" (aka protected) but technically it has no different behaviour.
The assignment to self.__y creates a new instance variable named _Test__y, i.e. its name is mangled so unless you use the mangled name it cannot be accessed from outside the class. This could be used for "private" variables.
The assignment to b creates a local variable. It is not available from anywhere but the __init__ function as it's not saved in the instance, class or global scope.
Declaring a variable at the top level of the class is like declaring a static or class variable. Qualifying it with self is declaring an instance variable. Class variables can be modified by referring to them by class name (e.g. Class.x = 5) and all instances will inherit these changes. Instance variables are private to an instance and can only be modified by that instance.
You can achieve some level of access control using underscores. See private variables in the Python tutorial. By convention, variables starting with one underscore, e.g. _foo are non-public parts of an API, and names starting with two underscores e.g. __foo will have it's name mangled to be _classname__foo.
Although answered, let me add some comments to your questions:
Declaring a variable in a class (outside of a function) : all class functions can access it (basically a public variable)
This is like a static variable and can be called using the class name. These variables are available to all functions, any functions can modify it and print it.
Declaring a variable inside a function inside a class : only that function can access it (it's in that function's scope):
If the variable is declared without self then it is accessible within that function only, like a local variable. However, if it was declared using self like self.var= 'somevalue', then it is accessible via any object but not via the class name.
Declaring a variable with self.(variable name) inside a function inside a class : all class functions can access it (how is this different from global (variable name)?)
See answer in the above part.
And since there is no private / protected, everything is public, so everything accessible from inside a class is accessible from outside the class
Yes, but we can use single underscore to tell the world this variable is private, but technically that actually doesn't make it private.
we can use the scope in this for as :
case 1: In the Class
class test:
def __init__(self, a):
self.__elements = a
def change_a(self): self.__elements = 5
case 2 : Outside class
t = test(5)
This will access by as object._classname__privatevaribalename
print(t._test__elements)
this will print the change value of a
I know class attributes are shared and can be accessed by all functions enclosed in the same class, but my question is what about variables enclosed in functions in a class?
I'm trying to create a GUI and my class is made up only of functions.
class Application():
def func_a(self):
self.x = Entry(text="My entry text")
def func_b(self):
self.x.config(width=100)
Can this work? Will the self.x variable in the first function be referred to by func_b if they're in the same class? How does Python deal with variables in different functions all enclosed in the same class? I suppose they will be shared but I have no idea.
Can this work? Will the self.x variable in the first function be referred to by func_b if they're in the same class?
Absolutely. But since the variable x is created only in func_a, it should have been called before func_b is called. Otherwise you will get an error.
How does Python deal with variables in different functions all enclosed in the same class? I suppose they will be shared
Since the instance variables are specific to the instances they are defined in, they will be available to all the methods in the class. In your case, when you do
self.x = ...
you are actually creating an attribute called x, in the current instance referred by self. So, if you invoke func_b with the same instance, it will work fine. For example,
# Create an instance
app = Application()
# Call `func_a` to create `x` in `app`
app.func_a()
# Check if it is present
print(app.x)
# Call `func_b` and now it should not fail
app.func_b()
Edit: As Gabriel mentions in the comments, try to create the instance variables in the __init__ (constructor) itself, so that you don't have to worry about the order of function calls.
Declaring a variable in a class (outside of a function): all class functions can access it (basically a public variable)
Declaring a variable inside a function inside a class: only that function can access it (it's in that function's scope)
Declaring a variable with self.(variable name) inside a function inside a class: all class functions can access it (how is this different from global (variable name)?)
And since there is no private/protected, everything is public, so everything accessible from inside a class is accessible from outside the class.
Are there any other nuances I should know, or have I pretty much got it?
Since the listing in your question is not 100% clear, I've decided to explain it with a simple example. It also includes some things like __something variables you did not mention in your list.
class Test:
a = None
b = None
def __init__(self, a):
print self.a
self.a = a
self._x = 123
self.__y = 123
b = 'meow'
At the beginning, a and b are only variables defined for the class itself - accessible via Test.a and Test.b and not specific to any instance.
When creating an instance of that class (which results in __init__ being executed):
print self.a doesn't find an instance variable and thus returns the class variable
self.a = a: a new instance variable a is created. This shadows the class variable so self.a will now reference the instance variable; to access the class variable you now have to use Test.a
The assignment to self._x creates a new instance variable. It's considered "not part of the public API" (aka protected) but technically it has no different behaviour.
The assignment to self.__y creates a new instance variable named _Test__y, i.e. its name is mangled so unless you use the mangled name it cannot be accessed from outside the class. This could be used for "private" variables.
The assignment to b creates a local variable. It is not available from anywhere but the __init__ function as it's not saved in the instance, class or global scope.
Declaring a variable at the top level of the class is like declaring a static or class variable. Qualifying it with self is declaring an instance variable. Class variables can be modified by referring to them by class name (e.g. Class.x = 5) and all instances will inherit these changes. Instance variables are private to an instance and can only be modified by that instance.
You can achieve some level of access control using underscores. See private variables in the Python tutorial. By convention, variables starting with one underscore, e.g. _foo are non-public parts of an API, and names starting with two underscores e.g. __foo will have it's name mangled to be _classname__foo.
Although answered, let me add some comments to your questions:
Declaring a variable in a class (outside of a function) : all class functions can access it (basically a public variable)
This is like a static variable and can be called using the class name. These variables are available to all functions, any functions can modify it and print it.
Declaring a variable inside a function inside a class : only that function can access it (it's in that function's scope):
If the variable is declared without self then it is accessible within that function only, like a local variable. However, if it was declared using self like self.var= 'somevalue', then it is accessible via any object but not via the class name.
Declaring a variable with self.(variable name) inside a function inside a class : all class functions can access it (how is this different from global (variable name)?)
See answer in the above part.
And since there is no private / protected, everything is public, so everything accessible from inside a class is accessible from outside the class
Yes, but we can use single underscore to tell the world this variable is private, but technically that actually doesn't make it private.
we can use the scope in this for as :
case 1: In the Class
class test:
def __init__(self, a):
self.__elements = a
def change_a(self): self.__elements = 5
case 2 : Outside class
t = test(5)
This will access by as object._classname__privatevaribalename
print(t._test__elements)
this will print the change value of a