Python的类与对象

之前学过的C++和Java都是面向对象的编程语言,因此对Pytho的面向对象的学习会更加轻松一点,这里记录一些python面向对象的基本用法

# 类定义
class People:
    # 定义基本属性
    name = ''
    age = 0
    # 定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0

    # 定义构造方法
    def __init__(self, n, a, w):
        self.name = n
        self.age = a
        self.__weight = w

    def speak(self):
        print("%s 说: 我 %d 岁。" % (self.name, self.age))


# 但继承实例
class Student(People):
    grade = ''

    def __init__(self, n, a, w, g):
        # 调用父类的构造函数
        People.__init__(self, n, a, w)
        self.grade = g

    # 覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))


# 另一个类,多继承之前的准备
class Speaker:
    topic = ''
    name = ''

    def __init__(self, n, t):
        self.name = n
        self.topic = t

    def speak(self):
        print("我叫 %s,我是一个演说家,我演讲的主题是 %s" % (self.name, self.topic))


# 多继承
class Sample(Speaker, Student):
    a = ''

    def __init__(self, n, a, w, g, t):
        Student.__init__(self, n, a, w, g)
        Speaker.__init__(self, n, t)


test = Sample("Tim", 25, 80, 4, "Python")
test.speak()  # 方法名同,默认调用的是在括号中排前地父类的方法

注意点1:

在Python中,有以下几种方式来定义变量:

  • xx:公有变量
  • _xx:单前置下划线,私有化属性或方法,类对象和子类可以访问,from somemodule import *禁止导入
  • __xx:双前置下划线,私有化属性或方法,无法在外部直接访问(名字重整所以访问不到)
  • __xx__:双前后下划线,系统定义名字(不要自己发明这样的名字)
  • xx_:单后置下划线,用于避免与Python关键词的冲突

例如 : 上面代码的__init__()是构造函数,在生成对象时调用,__weight这个是私有变量

注意点2:

继承:

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

需要注意圆括号中基类的顺序,若是基类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找基类中是否包含方法。

如:上面的代码Sample类对象test在调用speak()方法时调用的是它的父类中从左到右第一个的test方法(方法名同,默认调用的是在括号中排前地父类的方法

注意点3:

在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。

self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。

__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。

注意点4:

如果多继承中想调用不是第一个父类的同同名方法咋办?

例:在上面的代码中增加Sport类,并改写Sample类

class Sport:

    def __init__(self, n, a):
        self.name = n
        self.age = a

    # 覆写父类的方法
    def speak(self):
        print("%s 说: 我 %d 岁了,我爱好运动" % (self.name, self.age))


# 多继承
class Sample(Speaker, Student, Sport):
    a = ''

    def __init__(self, n, a, w, g, t):
        Student.__init__(self, n, a, w, g)
        Speaker.__init__(self, n, t)
        Sport.__init__(self, n, a)

如何调用Studen或者Sport类的speak方法呢?

在网上看了一些博客,找到了解决方法,在Sample类里重写speak方法,具体要调用哪个类的speak方法,然后使用不同的语句即可:

# 在Sample里增加speak方法:
    def speak(self):
        # super().speak()  # 调用Speaker的speak方法
        # super(Sample, self).speak()  # 调用Speaker的speak方法
        # super(Speaker, self).speak()  # 调用Student的speak方法
        # super(Student, self).speak()  # 调用Student父类的People的speak方法
        super(People, self).speak()  # 调用Sport的speak方法

这里出现了一个问题,在  super(Student, self).speak()   前面的都是对的,而写了这句话后期待出现的是调用Sport的speak方法,可是调用的却是People的speak方法(因为Student函数继承了People类)。这时发现了类名.__mro__(Method Resolution Order 方法解析顺序),打印了一下后发现了方法解析顺序,然后继续往下写了一下就好了。

 

 注意点5:

类的专有方法:

  • __init__ : 构造函数,在生成对象时调用
  • __del__ : 析构函数,释放对象时使用
  • __repr__ : 打印,转换
  • __setitem__ : 按照索引赋值
  • __getitem__: 按照索引获取值
  • __len__: 获得长度
  • __cmp__: 比较运算
  • __call__: 函数调用
  • __add__: 加运算
  • __sub__: 减运算
  • __mul__: 乘运算
  • __truediv__: 除运算
  • __mod__: 求余运算
  • __pow__: 乘方

注意点6:

运算符重载(对类的专有方法进行重载)

class Pair:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self):
        return self.x + self.y

    def __str__(self):
        return '(%d, %d)' % (self.x, self.y)


p = Pair(3, 4)
print(p)
print(p.__add__())

 

posted @ 2019-10-28 17:45  +D  阅读(216)  评论(0编辑  收藏  举报