1. 访问权限设置规则

与 C++、C#、Java 等语言相似,Python 支持将类的属性和方法设置成特定的访问权限,但不是通过关键字区分,而是通过下划线来区别的:下划线具有五大作用

  • 单前导下划线:告知变量或者方法是用于类的内部使用的,但不是强制性的(在类的外部使用通常是不会报错),但是也有例外:

(如果使用通配符从模块中导入所有名称,则Python不会导入带有前导下划线的名称)

  1. # This is my_module.py:
  2. def external_func():
  3. return 23
  4. def _internal_func():
  5. return 42
  6. >>> from my_module import *
  7. >>> external_func()
  8. 23
  9. >>> _internal_func()
  10. NameError: "name '_internal_func' is not defined"
  • 双前导下划线:变量和方法只能在类的内部被调用,不能在类的外部被调用,而且子类不能继承。原理:解释器执行到的时候,会更改变量或者方法的名称,为了在类被扩展的时候产生冲突。 ```python class Test: def init(self):
    1. self.foo = 11
    2. self._bar = 23
    3. self.__baz = 23

t = Test() dir(t) [‘Testbaz’, ‘class‘, ‘delattr‘, ‘dict‘, ‘dir‘, ‘doc‘, ‘eq‘, ‘format‘, ‘ge‘, ‘getattribute‘, ‘gt‘, ‘hash‘, ‘init‘, ‘le‘, ‘lt‘, ‘module‘, ‘ne‘, ‘new‘, ‘reduce‘, ‘reduceex‘, ‘repr‘, ‘setattr‘, ‘sizeof‘, ‘str‘, ‘subclasshook‘, ‘weakref‘, ‘_bar’, ‘foo’]

此时,baz在内部的名称是_Testbaz。

  1. <a name="WzsN8"></a>
  2. # 2. 变量/属性
  3. <a name="VQgXk"></a>
  4. ## 2.1 变量的创建
  5. python变量不需要声明数据类型,在首次赋值的时候创建变量。
  6. <a name="ejFC0"></a>
  7. ## 2.2 变量的分类
  8. 类中的变量有类变量、实例变量,同时为了更好的理解,本节将全局变量,局部变量一起讲解。
  9. | | 位置 | 调用 |
  10. | --- | --- | --- |
  11. | 全局变量 | 模块内,所有函数外,所有类外 | 类、函数中需要使用全局变量时,需要在类/函数中定义global |
  12. | 局部变量 | 函数内、class的方法(类方法、静态方法、实例方法)内,且变量前面没有修饰 | |
  13. | 类变量 | class内,不在class的任何方法内 | `**类名.变量名**` |
  14. | 实例变量 | class的方法内,使用self修饰 | `**self.变量名**` |
  15. 实例变量与类变量的相关问题:
  16. 1. `**实例变量.变量名、self.变量名**` 既可以调用类变量也可以调用实例变量,但是当类变量与实例变量同名时,则调用的是实例变量,此时需要调用类属性则必须使用`**类名.类属性**`
  17. 1. 其实在实例方法中调用类方法还可以通过`**global**`关键字,不会报错。
  18. ```python
  19. class Student:
  20. a = 1
  21. name = "wnagzhiwei"
  22. age = 23
  23. def __init__(self,name,age):
  24. self.name = name
  25. self.age = age
  26. @classmethod
  27. def writework(cls):
  28. global a
  29. a = 10
  30. print(cls.age)
  31. print(cls.name)
  32. print(a)
  33. s1 = cls("Tom",18)
  34. print(s1.name,s1.age)
  35. def eat(self):
  36. print(Student.name+"在吃饭")
  37. global a
  38. a = 20
  39. print(a)
  40. pass
  41. s = Student("jack",20)
  42. s.writework()
  43. s.eat()
  44. 23
  45. wnagzhiwei
  46. 10
  47. Tom 18
  48. wnagzhiwei在吃饭
  49. 20

3. 类中的方法

其实我们学习面向对象的时候,可以与java面向对象进行对比,这样能够学习的更加高效。
在调用方法的时候,一般都是用对象.方法

3.1 构造方法

python中的构造方法**__init__()**随着实例对象的创建而调用(在面试时拿来和**__new__()**,详情请点击)。构造方法特点有:

  • 一个类中只能有一个**__init__()**,创建多个的话,不会报错,但是只会执行最后一个。
  • 构造方法一般用来初始化实例变量,最好使用**self.变量名**来创建实例变量。 ```python class Student(): sum1 = 0 name = “ “ age = 0 def init(self):
    1. print("你好,python")
    def init(self,name1,age1):
    1. self.name = name1
    2. self.age = age1

def work(self): pass

在实例化Student的时候会执行最后一个init()。即实例化时,s = Student()会报错,显示没有传入参数。

  1. java类中创建多个构造方法,调用时会进行方法的重载,那么python能否创建多个构造方法实现重载呢?<br />其实也是可以的,但是一般使用类方法进行
  2. <a name="oUcWm"></a>
  3. ## 3.2 实例方法
  4. 实例方法中的第一个参数代表类的实例对象,默认命名为self(其他名字也可以),方法内部可以使用类变量和类方法:`**类名.类属性、类名.类方法**`**。**在调用实例方法时,推荐使用`**对象.实例方法**`,不推荐使用`**类.实例方法**`
  5. ```python
  6. class Student:
  7. a = 1
  8. name = "wnagzhiwei"
  9. age = 23
  10. def __init__(self,name,age):
  11. self.name = name
  12. self.age = age
  13. def eat(self):
  14. print(self.name+"在吃饭")
  15. pass
  16. s = Student("jack",20)
  17. # Student.eat()会报错
  18. Student.eat(s) # 传入对象就不会报错。在类的内部调用时,直接Student.ea(self)
  19. s.eat()

3.3 类方法

被装饰器**@classmethod**修饰,第一个参数为类的名字,默认命名为**cls**(起其他名字也可以),方法内部不能使用实例属性和实例方法。**self**则代表类的一个实例对象,**cls**代表类本身,在类的方法中可以通过**cls**创建一个实例化对象,进行实例属性的调用。
使用场景:类方法用于模拟java定义多个构造函数的情况。
调用方式:

  • **类名.类方法名()**
  • **实例对象.类方法名()**
    1. class Student:
    2. a = 1
    3. name = "wnagzhiwei"
    4. age = 23
    5. def __init__(self):
    6. pass
    7. @classmethod
    8. def override(cls,name,age):
    9. s = cls()
    10. s.name = name
    11. s.age = age
    12. return s
    13. def eat(self):
    14. print(self.name + "在吃饭")
    15. s1 = Student.override("Tom",18)
    16. s1.eat()
    17. s2 = Student()
    18. print(s2.name)

    3.4 静态方法

    静态方法被装饰器**@staticmethod**修饰,第一个参数既不代表实例对象本身,也不代表类本身。静态方法的调用可以是**类名.静态方法名、对象名.静态方法名**

    3.5 抽象方法

    抽象方法不能单独的使用**@abstractmethod**,必须先导入abc模块,因为**abstractmethod类装饰器**不在builtin模块中(抽象方法是在后面添加的特性)。abc模块是**abstract base classes**,里面有许多装饰器,但是3.3开始只保留了abstractmethod装饰器函数。

3.6 Property属性方法

属性方法被装饰器**@property**修饰,将类的方法变为属性,调用时,会被视为属性。新式类与旧式类的用法会不同。

3.7 类的其他魔法方法

3.8 新式类与旧式类

python2.3之前的类都是旧式类,之后有了新式类,继承了object的都是新式类,没有继承的就是旧式类
python3.x之后,所有的类默认继承了object类,所以都是新式类