当前位置: > > > Python - 类的定义与使用详解(附样例)

Python - 类的定义与使用详解(附样例)

    面向对象编程(oop)是一种程序设计思想。oop 把对象作为程序的基本单元,一个对象包含数据和操作数据的函数。同样作为面向对象编程语言,Python 的类提供了面向对象编程的所有标准特性:
  • 类继承机制允许多个基类,派生类可以覆盖它基类的任何方法,一个方法可以调用基类中相同名称的的方法。
  • 对象可以包含任意数量和类型的数据。
  • 和模块一样,类也拥有 Python 天然的动态特性:它们在运行时创建,可以在创建后修改。

1,类的定义

(1)定义类使用 class 关键字,class 后面紧接类名,无类继承时类名后可以加括号也可以不加括号:
注意:在定义实例变量、实例方法时的第一个参数必须是 selfself 其实就相当于 C++ 或者 Java 中的 this,不过在 pythonself 不是关键词,我们可以定义成 ab 或其它名字都可以,只是约定成俗都使用了self
#定义一个Person类
class Person:
    #定义一个类属性
    legs = 2
    #定义一个实例方法
    def run(self):
        print('running...')

(2)下面是对这个自定义类的简单实用样例:
注意:第 16 行代码 person1.legs = 1 对实例对象 person1legs 属性进行赋值后,就相当于覆盖了类对象 Personlegs 属性。而 person2 对象的 legs 没有赋值覆盖,因此引用的就是类对象的 legs 属性。
print("--- 访问类属性 ---")
print("Person.legs:", Person.legs)


print("--- 实例化对象 ---")
person1 = Person()
person2 = Person()
#访问对象属性
print("person1.legs:", person1.legs)
print("person2.legs:", person2.legs)
#访问对象方法
person1.run()
person2.run()

print("--- 修改对象属性、类属性 ---")
person1.legs = 1 
Person.legs = 3
print("person1.legs:", person1.legs)
print("person2.legs:", person2.legs)

2,类属性

    Python 作为动态语言,类对象和实例对象都可以在运行时绑定任意属性。因此,类属性除了可以在类定义时就绑定,也可以在运行时任意阶段进行绑定(增加属性,删除属性):
#定义一个Person类
class Person:
    #定义一个类属性
    legs = 2
    #定义一个实例方法
    def run(self):
        print('running...')

#在运行时添加类属性
Person.hangs = 2

#实例化对象
person = Person()
print("person.legs:", person.legs)
print("person.hangs:", person.hangs)

3,实例属性

(1)如果某个属性对于每个实例都是独有的,通常我们会在 __init__ 构造方法中将其定义为实例变量:
提示:在类中可以使用“self.实例属性名”来调用实例属性,在类外可以使用“实例名.实例属性名”来调用实例属性。
#定义一个Person类
class Person:
    #定义一个类属性
    legs = 2
    #构造方法
    def __init__(self,name,age):
        self.name = name
        self.age = age
    #定义一个实例方法
    def run(self):
        print('%s is running...' % self.name)

#实例化对象
person = Person("hangge", 100)
print("person.legs", person.legs)
print("person.name", person.name)
print("person.age", person.age)
person.run()

(2)实例变量不是说一定要在 __init__ 构造方法中定义,在类的其他自定义方法中也可以定义。甚至可以直接使用 objname.attr = attr_value 的方式给对象绑定属性(新增属性):
#定义一个Person类
class Person:
    #定义一个属性
    legs = 2
    #设置姓名
    def setName(self,name):
        self.name = name
    #定义一个方法
    def run(self):
        print('%s is running...' % self.name)

#实例化对象
person = Person()
person.setName('hangge')
person.age = 99
print("person.legs", person.legs)
print("person.name", person.name)
print("person.age", person.age)
person.run()

4,类方法

(1)类方法和实例方法类似,不同之处在于:
  • 类方法需要使用修饰语句:@classmethod
  • 类方法至少需要包含一个参数,与实例方法不同的是该参数并非 self,而是 python 程序员约定俗成的参数:clscls 表示当前类对象)
  • 类方法中是不能调用实例变量的,但是可以调用类变量
#定义一个Person类
class Person:
    #定义一个类属性
    legs = 2
    #定义一个实例方法
    def run(self):
        print('running...')
    #定义一个类方法
    @classmethod
    def info(cls):
        print("legs:", cls.legs)

(2)类方法的调用注意如下事项:
  • 类方法推荐使用类名直接调用,当然也可以使用实例对象来调用(不推荐)
  • Python 会自动将类本身绑定到 cls 参数(非实例对象),故在调用类方法时,无需显式为 cls 参数传递参数。
 Person.info()

5,静态方法

(1)静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但是和类本身没有关系,它仅仅托管于某个类的名称空间中,便于使用和维护。定义一个静态方法要注意如下事项:
  • 类静态方法需要使用 @staticmethod 修饰
  • 类静态方法没有 selfcls 这样的特殊参数,故 Python 解释器不会对其包含的参数做任何类或对象的绑定
  • 类静态方法中无法调用任何类和对象的属性和方法,类静态方法与类的关系不大
#定义一个Person类
class Person:
    #定义一个静态方法
    @staticmethod
    def say(name, words):
        print('%s: %s' % (name, words))

(2)静态方法的调用,既可以使用类名,也可以使用类对象:
Person.say('hangge', 'Welcome to hangge.com')

6,继承、共有属性、私有属性

(1)类的公有属性在任何地方都能访问。而私有属性只有在类的内部才能访问(即使是子类内部也不能访问父类的私有属性)。要定义一个私有属性,只需在名称前面加两个下划线。
注意Python 并没有真正的私有化属性,尽管通过前面加下划线的方式将属性私有化了,但其实是伪私有。我们仍然可以通过“对象._类名__私有字段名”(如:son._Father__info)来强制访问私有属性。不过这种方式并不推荐,建议通过 getter 方法或者 @property 的方式来获得私有属性。

(2)下面定义两个类并在父类中添加一个私有属性进行测试:
#定义一个Father类
class Father:
    #定义一个公有属性
    info = "public"
    #定义一个私有属性
    __info = "private"

    def __init__(self,name):
        self.name = name
    def get_name(self):
        return self.name
    def printInfo(self):
        print("--- Father Info ---")
        print("Father.info: %s" % Father.info)
        print("Father.__info: %s" % Father.__info)

#定义一个Son类,继承Father类
class Son(Father):
    def __init__(self,name,age):
        self.age = age
        super().__init__(name)
    def get_age(self):
        return self.age
    def printInfo(self):
        print("--- Son Info ---")
        print("Son.info: %s" % Son.info)
        print("Son.__info: %s" % Son.__info)

(2)实例化一个 Father 类并进行测试,可以看到外部无法访问私有属性:
#实例化一个Father类
father = Father("Father")
father.printInfo()
print(father.info)
print(father.__info)

(3)实例化一个 Son 类进行测试,发现子类内部也是无法访问父类的私有属性:
#实例化一个Son类
son = Son("Son",18)
print(Son.info)
son.printInfo()

附:多继承会调用哪个父类的函数?

(1)Python 是支持多继承的,也就是说一个子类可以同时有多个基类。如果继承了多个父类,且父类都有同名方法,则默认只执行第一个父类的方法:
#定义两个父类
class A:
    def get(self):
        print("get A")

class B:
    def get(self):
        print("get B")

#定义一个子类
class C(A, B):
    def __init__(self):
        print("this is class C")

#开始测试
c = C()
c.get()

(2)对于 __init__ 构造方法也是同理,如果子类无 __init__,则会调用 第一个父类的 __init__
#定义两个父类
class A:
    def __init__(self):
        print("this is class A")

class B:
    def __init__(self):
        print("this is class C")

#定义一个子类
class C(A, B):
    def get(self):
        print("get C")

#开始测试
c = C()
c.get()

评论0