Python 快速入门笔记(7):类和对象
本系列随笔是本人的学习笔记,初学阶段难免会有理解不当之处,错误之处恳请指正。转载请注明出处:https:////www.cnblogs.com/itwhite/p/12298858.html。
类的定义
示例:
class Person: count = 0 # 类的属性,所有对象共享 def __init__(self, name, age): # 构造函数 self.name = name # 对象的属性 self.age = age Person.count += 1 def foo(self): # 普通成员方法(对象方法),self 相当于 C++ 中的 this 指针 print("Hi! My name is %s, I'm %d years old." % (self.name, self.age)) @staticmethod # 静态方法 def staticFoo(): print("%d objects were created" % (Person.count)) @classmethod # 类的方法,使用时与静态方法一样 def classFoo(cls): print("%d objects were created" % (cls.count)) jack = Person("Jack", 23) # 创建对象 bob = Person("Bob", 25) jack.foo() # 调用普通成员方法 print(jack.age) # 直接访问对象属性 print(Person.count) # 直接访问类的属性 print(jack.count) # 使用对象访问类的属性 Person.staticFoo() # 调用静态方法 Person.classFoo() # 调用类的方法 jack.staticFoo() # 使用对象访问静态方法 jack.classFoo() # 使用对象访问类的方法
继承
示例:
class A: pass class B (A): # B 继承自 A pass class C: pass class D (B, C): # 多重继承,D 继承自 B 和 C pass
一些类与类、对象与类之间的判断方法:
# 1. 判断某个类是否是另一个类的子类,使用内置函数 issubclass() print(issubclass(D, A)) # True print(issubclass(C, A)) # False # 2. 获取某个类的基类,使用特殊属性 __bases__ print(D.__bases__) # (<class __main__.B at 0x00000000024E68E8>, <class __main__.C at 0x00000000024E6888>) # 3. 判断某个对象是否是某个类的实例,使用内置函数 isinstance() c = C() d = D() print(isinstance(c, C)) # True print(isinstance(c, A)) # False print(isinstance(d, B)) # True print(isinstance(d, C)) # True print(isinstance(d, D)) # True # 4. 获取某个对象所属的类,使用特殊属性 __class__ print(c.__class__) # __main__.C print(d.__class__) # __main__.D
# 5. 查看对象的所有属性及值,使用特殊属性 __dict__
print(d.__dict__) # {},因为前面并未设置对象属性,因此这里为空
抽象类和抽象方法
示例:
from abc import ABC, abstractmethod class A (ABC): # 抽象类 def __init__(self): self.data = 123 @abstractmethod def foo(self): # 抽象方法 pass def bar(self): # 普通方法 pass class D (A): def __init__(self): A.__init__(self) def foo(self): print(self.data) d = D() d.foo() # a = A() # 抽象类不能实例化:TypeError: Can't instantiate abstract class A with abstract methods foo
旧式类与新式类
Python 中类的定义支持以下三种写法(python 2.x 和 3.x 都支持,但是意义略有差别):
class Person(object): pass #1 class Person(): pass #2 class Person: pass #3
说明:
- 在 python 3.x 中,以上三种写法效果一致,都是新式类的写法;
- 在 python 2.x 中,#1 是新式类的写法,#2 和 #3 都是旧式类的写法,一般使用 #1 的写法。
super():子类中调用父类方法
有时候需要在子类中调用父类方法来初始化,例如:
class A: def __init__(self): print("A::__init__() is called") self.foo = 123 class B (A): def __init__(self): A.__init__(self) # 直接通过类名调用父类中定义的方法 b = B() # A::__init__() is called
python 中定义了 super() 方法用来调用父类方法并推荐使用,但是个人觉得并不是太好,一方面 python 2.x 和 python 3.x 中的使用方式不一样,另一方面当有多重继承时无法控制调用哪些父类的方法,例如:
# python 2.x 版本 class A (object): # 基类必须是新式类 def __init__(self): print("A::__init__() is called") self.foo = 123 class B (object): def __init__(self): print("B::__init__() is called") self.bar = 456 class C (A, B): def __init__(self): super(C, self).__init__() # 或者 super(self.__class__, self),super() 中需要参数 c = C() # A::__init__() is called # python 3.x 版本 class A: # 默认就是新式类了 def __init__(self): print("A::__init__() is called") self.foo = 123 class B: def __init__(self): print("B::__init__() is called") self.bar = 456 class C: def __init__(self): super().__init__() # super() 中不需要参数 c = C() # A::__init__() is called
上面的示例中,通过 super() 只能调用父类 A 的构造函数,而父类 B 的构造函数没能调用,bar 属性无法得到初始化,这也是个人不喜欢 super() 的原因,不知道有没有别的好的解决方法。
类的嵌套
示例:
class A: class B: # 类嵌套 def foo(self): print("B::foo() is called") def foo(self): print("A::foo() is called") class C: # 方法中定义类 def foo(self): print("C::foo() is called") c = C() return c a = A() b = A.B() c = a.foo() # A::foo() is called b.foo() # B::foo() is called c.foo() # C::foo() is called
对象方法与普通函数
示例:
class A: def __init__(self, data): self.data = data def foo(self): # 对象方法 print("A::foo() is called, data is %d" % (self.data)) def bar(obj): # 普通函数 print("bar() is called, data is %d" % (obj.data)) a1 = A(123) a1.foo() # A::foo() is called, data is 123 a1.foo = bar # 这里能够替换 对象的方法 哦 a1.foo(a1) # bar() is called, data is 123 a2 = A(456) qux = a2.foo # 调用时会自动传入 a2 对象哦 qux() # A::foo() is called, data is 456
完。