python基础--类的属性&方法&继承
2017-12-29 本文已影响0人
sandy测试路
面向对象编程
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。所以面向对象编程首先考虑的是新建类创建一个对象!
- 面向对象编程的三大基本特性: 封装,继承,多态。
- 多态指的是:子类既是自身类的实例也是父类的实例,因此任何父类实例可以使用的方法,其所有的子类实例都可以使用,不需要任何修改,这就是多态。实际上也是著名的 ‘开闭’原则 : 对扩展开放(允许增加类的子类),对修改封闭(不需要修改依赖父类型的方法,即所有的父类型包括其子类型都可以调用)。
- 通过内置函数
isinstance(obj, class_or_tuple, /)
,判断对象是否是类或者其子类的实例
python中类的属性和实例属性
-
python没有new关键字 ,python直接通过类名ClassName(),进行初始化类的实例对象。
-
类属性:类对象(即类名)所拥有的属性,它被该类的所有实例对象所共有,可以通过类名和实例对象访问类属性,在内存中只存在一个副本。类似于Java,C++中类的静态成员变量。
-
公有的类属性
,在类外可以通过类对象和实例对象访问。 -
私有的类属性__privateattr
, 以双下划线开头的变量,只允许在类本身中通过类对象和实例对象进行访问,不允许在类外部进行访问。 -
保护的类属性_protectedattr
,以单下划线开头的变量,只允许其本身和其子类中通过类对象和实例对象访问,不能from module import *
-
-
修改类属性:必须使用类对象调用,通过类对象修改类属性后该类属性仍然被所有实例对象所共有,如果使用实例变量修改类属性那么该实例对象会产生一个同名的实例属性。
-
实例属性:属于实例对象本身,类对象无法访问,在整个类中可以调用,在类外部不可调用。实例属性的优先级高于同名类属性,应尽量避免同名的实例属性和类属性。
class B(object):
num = 0 # 公有的类属性
__age = 24 # 私有的类属性
_sex = 'female' # 保护的类属性
def get_age(self):
print(self.__age) # 或者 B.__age也可以,通过类名或者实例对象self调用类属性
def set_name(self, name):
self.name = name # 实例对象的实例属性
def get_name(self):
return self.name # 类中调用实例属性
b1 ,b2 = B(), B()
print(B.num) # 类名访问类属性,输出: 0
print(b1.bum) # 实例对象访问类属性,输出:0
print(b1.__age) # 报错,私有的类属性只允许在类里面访问
b1.num = 1 # 通过实例对象修改类属性,该实例对象会产生一个同名的实例属性。对该实例对象来说,优先级高于同名类属性
print(b1.num) # b1的实例属性num,输出:1
print(b2.num) # 输出:0
print(B.num) # 类属性不变,输出:0
B.num = 2 # 通过类对象修改类属性
print(b1.num) # 输出:1
print(b2.num) # 输出:2
b1.num = 1
del(b1.num) # 删除实例对象的实例属性
print(b1.num) # b1实例上的num属性已被删除所以会去类里面找同名的类属性,输出:0
python中类方法和实例方法和静态方法
-
类方法
:通过内置函数classmethod()
或者修饰器@classmethod
定义,定义时必须指定第一个参数,通常用cls
。类方法可以通过类对象和实例对象访问,调用类方法时不需要指定第一个参数cls。 -
实例方法
:定义时必须指定第一个参数,通常是self
,self代表的是调用该方法的实例对象。实例方法只能通过实例对象访问,调用实例方法时不需要传递第一个参数self。 -
静态方法
:通过内置函数staticmethod()
或者修饰器@staticmethod
定义,不需指定第一个默认参数。静态方法可以通过类对象和实例对象访问。
- 公有的类方法/实例方法/静态方法
method()
: 可以在任何地方调用。 - 私有的类方法/实例方法/静态方法
__privatemethod()
: 只允许在类内部调用。 - 保护的类方法/实例方法/静态方法
_protectedmethod()
: 只能在当前类和其子类中调用。 -
类的专有方法
__method__()
,以双下划线开头并结尾的方法,一般是系统定义的是特殊方法,例如构造函数__init__()
,析构函数__del__()
,调用方式:ClassName.__init__()
class A(object):
def __init__(self, arg): # 类的构造函数__init__()
self.arg = arg
def test_1(self):
print('instance method test_1')
@classmethod
def test_2(cls):
print('class method test_2')
print(cls.__name__) # 调用此类方法的类名
def test_3(cls):
print('method test_3')
test_3 = classmethod(test_3) # 将方法变为类方法,效果同@classmethod
@staticmethod
def test_4():
print('static method test_4')
def _test_5(self):
print('protect instance method _test_5')
def __test_6(self):
print('private instance method __test_6')
a = A() # 初始化类的实例对象, <__main__.A instance at 0x0000000004C63A88>,0x0000000004C63A88表示实实在在的内存地址
# 调用实例方法:公有的,保护的,私有的
a.test_1() # 实例对象调用方法时会将自己作为第一个参数传递给方法
a._test_5()
a.__test_6() # 报错,内外面调用类的私有实例方法
# 调用类方法: 公有的,保护的,私有的
A.test_2()
a.test_2()
# 调用静态方法: 公有的,保护的,私有的
a.test_4()
A.test_4()
- 实例对象调用方法时默认会将自己作为第一个参数传递给方法,类对象调用方法时默认不会传递任何参数
class A():
def test1():
print("test1")
def test2(name):
print(name)
a = A()
a.test1() # 报错,TypeError: test1() takes 0 positional arguments but 1 was given,实例对象调用方法时会将自身a作为参数传递给test1()
A.test1() # 输出:test1
a.test2() # 输出:<__main__.A object at 0x0000021F953F7F60>,即输出对象a
A.test2() # 报错:TypeError: test2() missing 1 required positional argument: 'name'
A.test2("测试") # 输出:测试
继承
- python2中定义类时最好继承内置的基类object,python3中已经默认加上即使没有显示声明。
- python支持多继承,写法:class A(B,C,..):
- 继承的基类从左到右优先级逐渐降低,即查找方法时从左到右在基类中查找
- 子类实例可以直接调用父类的公有的和保护的实例方法,公有的和保护的静态方法
- 子类可以直接调用父类的公有的和保护的类方法
-
方法重写override
,子类重写父类的方法
class A:
def test(self):
print('A')
class B:
def test(self)
print('B')
class C(B, A):
def testC(self):
print('C')
c = C()
c.test() # 根据对象方法查找路劲从左到右在基类中查找。返回:'B'