
Python小白首选,输入优惠码“python”立减10元

作者 | 天元浪子
责编 | 刘静
出品 | 优快云 博客

class A:
def __init__(self):
""" 构造函数"""
self.a = 10 # 定义了一个成员变量a
def getA(self):
"""成员函数"""
print("a=%d" % self.a)
def __del__():
"""析构函数"""
print("delete object")
a = A()
a.getA()
当类被实例化为对象时,首先执行构造函数,当对象被销毁时,会自动执行析构函数。一般的,我们会在构造函数中进行初始化工作,在析构函数中进行清理工作。
>>> class A:
pass
>>> a = A()
>>> del a
>>> a
Traceback (most recent call last):
File "<pyshell#70>", line 1, in <module>
a
NameError: name 'a' is not defined
>>> class B:
def __del__(self):
print('执行析构函数,清理现场')
>>> b = B()
>>> del b
执行析构函数,清理现场
>>> b
Traceback (most recent call last):
File "<pyshell#75>", line 1, in <module>
b
NameError: name 'b' is not defined
在PY2中,类有新式类和旧式类两种。新式类需要继承自虚类Object,旧式类则不需要。PY2中类的写法有三种:
class A(object):新式类写法
class A():旧式类写法
class A:旧式类写法
在PY3中,只有新式类,不再支持旧式类。你如果习惯继承Object的写法,也完全没有问题。上面三种写法在PY3中都被解释成新式类。新式类和旧式类的主要区别是:
新式类可以继承Object的构造函数和析构函数,如果类的构造和析构函数没有特别的工作,可以省略。而旧式类则不能:
class A():
def print(self):
print("I am A")
class B(A):
def __init__(self):
A.__init__(self)
b = B()
class A(object):
def print(self):
print("I am A")
class B(A):
def __init__(self):
A.__init__(self)
b = B()
新式类可以使用super:
class A(object):
def print(self):
print("I am A")
class B(A):
def __init__(self):
super(A, self).__init__()
b = B()
多重继承时,各父类的初始化和函数查找顺序不同:旧式类为深度优先继承,新式类为广度优先继承。
>>> class A:
static_x = 10 # 静态变量
def __init__(self):
self.instance_y = 5 # 实例变量
>>> a = A()
>>> a.static_x
10
>>> a.instance_y
5
>>> A.static_x
10
>>> A.instance_y
Traceback (most recent call last):
File "<pyshell#89>", line 1, in <module>
A.instance_y
AttributeError: type object 'A' has no attribute 'instance_y'
class A:
static_x= 10
def __init__(self):
self.y = 10
@staticmethod
def staticFuc():
print(A.static_x)
@classmethod
def classFuc(cls):
print(cls.static_x)
A.staticFuc()
A.classFuc()
Staticmethod 函数不能使用Self参数,因此不成访问任何成员变量,只能通过类名访问类的静态变量。
class Animal:
def eat(self):
print('我能吃')
class Brid(Animal):
def __init__(self):
Animal.__init__(self)
def fly(self):
print('我会飞')
brid = Brid()
brid.eat()
brid.fly()
class Deer:
def showHorns(self):
print('我有鹿角')
class Horse:
def showFace(self):
print('我有马脸')
class Cow:
def showHoof(self):
print('我有牛蹄')
class Donkey:
def showTail(self):
print('我有驴尾')
class Milu(Deer, Horse, Cow, Donkey): # 多继承派生出一个四不像类
def __init__(self):
Deer.__init__(self)
Horse.__init__(self)
Cow.__init__(self)
Donkey.__init__(self)
milu = Milu()
milu.showHorns()
milu.showFace()
milu.showHoof()
milu.showTail()
不管是单继承还是多继承,都可以在派生类中重写父类的函数——这叫做覆盖。
公有成员:对类外部的任何代码可见;
保护成员:对类外部的任何代码都不可见,但对派生类可见;
私有成员:对类外部及派生类都不可见。
-
以英文字母开头的成员为公有成员
-
以一个下划线开头的成员为保护成员
-
以两个下划线开关的成员为私有成员
>>> class A(object):
def __init__(self, a, b, c):
self.a = 10 # 公有
self._b = b # 保护
self.__c = c # 私有
def getA(self): # 公有
return self.a
def setA(self, a): # 公有
self.a = a
def getB(self): # 公有
return self._b
def _setB(self, b): # 保护
self._b = b
def getC(self): # 公有
return self.__c
def __setC(self, c): # 私有
self.__c = c
>>> a = A(10, 20, 30)
>>> class B(A):
pass
>>> b = B(10, 20, 30)
>>> a.a
10
>>> a.getA()
10
>>> a.setA(5)
>>> a.a
5
>>> b.a
10
>>> b.getA()
10
>>> b.setA(5)
>>> b.a
5
>>> a.__c
Traceback (most recent call last):
File "<pyshell#85>", line 1, in <module>
a.__c
AttributeError: 'A' object has no attribute '__c'
>>> a.getC()
30
>>> a.__setC(5)
Traceback (most recent call last):
File "<pyshell#87>", line 1, in <module>
a.__setC(5)
AttributeError: 'A' object has no attribute '__setC'
>>> b.__c
Traceback (most recent call last):
File "<pyshell#88>", line 1, in <module>
b.__c
AttributeError: 'B' object has no attribute '__c'
>>> b.getC()
30
>>> b.__setC()
Traceback (most recent call last):
File "<pyshell#90>", line 1, in <module>
b.__setC()
AttributeError: 'B' object has no attribute '__setC'
私有成员的访问规则也与C++相同。那我为什么跳过保护成员了?来试试吧:
>>> a._b
20
>>> a._setB(5)
>>> a._b
5
看到这里就已经不对了,应该只有类内部的代码和派生类能使用啊,怎么可以直接用了呢?是的,Python的保护成员访问规则与C++的确实不一样。那 Python 的保护成员是什么样的机制呢?原来,在 Python 的OOP中,保护成员公有成员没有任何区别。保护规则仅适用于 from xxx import * 这一种情况。
testA.py
class A(object):
pass
class _B(object):
pass
testB.py
from testA import *
a = A()
b = _B()
Traceback (most recent call last):
File "testB.py", line 4, in <module>
b = _B()
NameError: name '_B' is not defined
from testA import A, _B
a = A()
b = _B()
import testA
a = testA.A()
b = testA._B()
class H2O(object):
def what(self):
print("I am H2O")
class Water(H2O):
def what(self):
print("I am water")
class Ice(H2O):
def what(self):
print("I am ice")
class WaterVapor(H2O):
def what(self):
print("I am water vapor");
def what(obj):
obj.what()
objs = [H2O(), Water(), Ice(), WaterVapor()]
for obj in objs:
what(obj)
>>> import abc
>>> class A(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def a(self):
pass
@abc.abstractmethod
def b(self):
pass
>>> class C(A):
def a(self):
print("a")
>>> c = C()
Traceback (most recent call last):
File "<pyshell#127>", line 1, in <module>
c = C()
TypeError: Can't instantiate abstract class C with abstract methods b

单例模式
def Singleton(cls):
_instance = {}
def _singleton(*args, **kargs):
if cls not in _instance:
_instance[cls] = cls(*args, **kargs)
return _instance[cls]
return _singleton
@Singleton
class Config(object):
pass
cfg1 = Config()
cfg2 = Config()
print(cfg1 is cfg2)

后记


点击阅读原文,精彩继续。
Python OOP精讲
本文深入浅出地讲解了Python面向对象编程(OOP)的核心概念,包括类和对象的定义、实例化、成员变量和函数,以及继承、封装、多态等面向对象编程的三大要素。同时介绍了Python中类的静态变量、实例变量、静态函数和类方法的使用,以及抽象类、单例模式的设计思想。

1万+

被折叠的 条评论
为什么被折叠?



