The Idea of "class" in python

I have studied Python recently and I found little differences between python and other programming languages.

class definition:

class Person(SuperClass, SuperClass2): # multiple inheritance is possible
  i = 1 # class variable

  # constructor
  def __init__(self, name, age): # "self" variable is required as first argument.
    self.name = name
    self.age = age

  @classmethod
  def say(cls, str): # class method requires "cls" variable as first argument.
    print(str)

p = Person("Paul", 28) # instantiation

Instance variables in method are set "self." as prefix. Any symbols like "@" are not required. it's different from ruby.

If you add some instance variable, you can write codes below.

p.height = 180

You don't have to define "height" variable in class definition previously. But if you want to limit making variables in the class, you can use the idea of "slot".

class A:
  __slot__ = ['a', 'b']
  def __init__(self):
    self.a = 1

i = A()
i.a      #=> 1

i.b = 2
i.b      #=> 2

i.c = 3  #=> raise AttributeError

And I was surprised that there are no strict idea of "private" in python. If you want to make pseudo private function or variable, I have to do below:

  1. add underscore(_) at head of function name or variable name
    • ex. _size, _function
    • This is just a convention. These functions and variables are accessible from outside of the class.
  2. add two underscore(__) at head of function name or variable name
    • ex. __size, __function
    • According this writing, the function name and variable name are replaced another name.

Except for above there may be lots of feature in python, I'll write up them next time.

2013/04/21 added

When "@classmethod" decorator is added to a function in some class and then the function is called, python interpreter seems to just give the class itself to first argument of the function.

class Test:
  def func(self):
    print(self, "func")
       
  @classmethod
  def class_func(cls):
    print(cls, "class_func")

instance = Test()

instance.class_func() #=> <class> "class_func"
instance.func()       #=> <object> "func"
Test.class_func()     #=> <class> "class_func"
Test.func()           #=> ERROR(the number of argument doesn't match.)