zoukankan      html  css  js  c++  java
  • 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

    完。

  • 相关阅读:
    TypeScript reflect-metadata 结合方法装饰器实现的一个自定义语法检查的例子
    使用 TypeScript 自定义装饰器给类的方法增添监听器 Listener
    爬取本blog所有文章链接
    90分钟掌握Python多线程爬虫(全程实战)
    python学习笔记
    Python零基础爬虫教学(实战案例手把手Python爬虫教学)
    开发,功能测试点,注意
    workerman
    tp6 文档
    公共方法
  • 原文地址:https://www.cnblogs.com/itwhite/p/12298858.html
Copyright © 2011-2022 走看看