数据类型、函数、面向对象

Python 各进制的表示与转换

Python 用 ob 表示二进制

二进制转十进制

>>> 0b10
2
>>> 0b11
3

0o 表示八进制

八进制转十进制

>>> 0o10
8
>>> 0o11
9

0x 表示十六进制

十六进制转十进制

>>> 0x10
16
>>> 0x1F
31

其他进制转二进制使用 bin() 函数

>>> bin(10)
'0b1010'
>>> bin(0o7)
'0b111'
>>> bin(0xE)
'0b1110'

其他进制转十进制使用 int() 函数

>>> int(0b111)
7
>>> int(0o77)
63
>>> int(0xE)
14

其他进制转十六进制使用 hex 函数

>>> hex(888)
'0x378'
>>> hex(0o7777)
'0xfff'
>>> hex(0b111)
'0x7'

其他进制转八进制使用 oct() 函数

>>> oct(0b111)
'0o7'
>>> oct(888)
'0o1570'
>>> oct(0x777)
'0o3567'

基本数据类型

  • number
    • int
    • float
    • bool
      • Ture
      • Flase
  • 序列 有序,可以索引取值,切片,常用操作:+*innot inlenmaxmin
    • str 不可变
    • list 可变
    • tuple 不可变
  • Set 集合 无序,可变,可以 - 求差集, & 求交集, | 求并集
  • Dict 字典,无序,可变

number

>>> type(1*1)

>>> type(1*1.0)

>>> type(2/2)

>>> type(2//2)

>>> type(True)

>>> type(False)

>>> int(True)
1
>>> int(False)
0
>>> bool(1)
True
>>> bool(0)
False
>>> bool('abc')
True
>>> bool('')
False
>>> bool([1,2,3])
True
>>> bool([])
False
>>> bool(None)
False

字符串 str

原始字符串

在字符串前面加 r 表示原始字符串,即所见即所得

>>> print(r'hello /n world')
hello /n world

字符串运算

字符串拼接

>>> 'hello' + 'world'
'helloworld'
>>> 
>>> 'hello' * 3
'hellohellohello'

索引

>>> 'hello world'[0]
'h'
>>> 'hello world'[1]
'e'
>>> 'hello world'[4]
'o'
>>> 'hello world'[-1]
'd'
>>> 'hello world'[-3]
'r'

切片

>>> 'hello world'[0:4]
'hell'
>>> 'hello world'[0:5]
'hello'
>>> 'hello world'[0:-1]
'hello worl'
>>> 'hello world'[6:10]
'worl'
>>> 'hello world'[6:11]
'world'
>>> 'hello world'[6:-1]
'worl'
>>> 'hello world'[6:]
'world'
>>> 'hello world'[-5:]
'world'

列表 list

定义列表

>>> ['hello', 1,2,3, True]
['hello', 1, 2, 3, True]

嵌套列表

>>> [['hello', 'world'], [1, 2], [True, False]]
[['hello', 'world'], [1, 2], [True, False]]

列表的基本操作

索引

>>> [1, 2, 3, 4][0]
1
>>> [1, 2, 3, 4][2]
3

切片,返回的是列表

>>> [1, 2, 3, 4][0:2]
[1, 2]
>>> [1, 2, 3, 4][-1:]
[4]

拼接

>>> [1, 2, 3, 4] + ['a', 'b']
[1, 2, 3, 4, 'a', 'b']

>>> [1, 2, 3, 4, 'a', 'b'] * 2
[1, 2, 3, 4, 'a', 'b', 1, 2, 3, 4, 'a', 'b']

元组 tuple

定义元祖

>>> (-1, 'hello', True)
(-1, 'hello', True)

元祖的基本操作

>>> (1, 2, 3)[0]
1
>>> (1, 2, 3)[-2:]
(2, 3)
>>> (1, 2) + ('a', 'b')
(1, 2, 'a', 'b')
>>> (1, 'a') * 2
(1, 'a', 1, 'a')

() 中只有一个元素的时候,python 会默认把 () 当做运算符,像是:(1 + 1) * 2 中的 ()

>>> type((1, 2, 3))

>>> type((1))

>>> type(('hello'))

如果想要定义只有一个元素的元组,可以在元素后面加一个英文逗号

>>> type((1,))

定义空元组

>>> type(())

已经有了列表,为什么需要元组?
为了代码稳定性。不可改变的元组类型有它的优势,因为当尝试修改元组的时候,会报错,避免错误隐藏在代码中。所以,列表和元组,优先选择使用元组,前提是存储的数据是静态的,不需要改变,如果存储的数据是动态的,需要改变,那么还是要用列表。

集合 set

定义集合

>>> {1, 2, 3, 'hello'}
{1, 2, 3, 'hello'}

序列有序,集合无序,所以集合无法索引取值

>>> {1, 2, 3}[0]
:1: SyntaxWarning: 'set' object is not subscriptable; perhaps you missed a comma?
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'set' object is not subscriptable

序列有序,集合无序,所以集合无法切片

>>> {1, 2, 3}[-2:]
:1: SyntaxWarning: 'set' object is not subscriptable; perhaps you missed a comma?
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'set' object is not subscriptable

集合的元素不能重复

>>> {1, 1, 2, 2, 3, 3}
{1, 2, 3}

集合的基本操作

>>> len({1, 2, 3})
3
>>> 2 in {1, 2, 3}
True
>>> 2 not in {1, 2, 3}
False
>>> {1, 2, 3, 4, 5, 6} - {3, 4}
{1, 2, 5, 6}
>>> {1, 2, 3, 4, 5, 6} & {3, 4, 7}
{3, 4}
>>> {1, 2, 3, 4, 5, 6} | {3, 4, 7}
{1, 2, 3, 4, 5, 6, 7}

定义一个空集合

>>> type({})

>>> type(set())

字典 dict

定义字典

>>> {1:'a', 2:'b', 3:'c'}
{1: 'a', 2: 'b', 3: 'c'}

Key 不能重复

>>> {1:'a', 1:'b', 3:'c'}
{1: 'b', 3: 'c'}

Key 不可变

>>> {[1,2]:'a', 1:'b', 3:'c'}
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: 'list'
>>> {(1,2):'a', 1:'b', 3:'c'}
{(1, 2): 'a', 1: 'b', 3: 'c'}

变量与运算符

值类型和引用类型

>>> a = 1
>>> b = a
>>> a = 3
>>> print(a)
3
>>> print(b)
1

>>> a = [1, 2, 3]
>>> b = a
>>> a[0] = 'x'
>>> print(a)
['x', 2, 3]
>>> print(b)
['x', 2, 3]

int 属于值类型,不可变;list 属于引用类型,可变。由于 int 不可改变,所以当 a = 3a 进行重新赋值的时候,a 指向了一个新的值;当 a[0] = ['x'] 修改了原来的值,a 不需要指向一个新的值,因为 list 是可变的。

值类型包括:int str tuple

引用类型包括:list set dict

不可变的字符串:

>>> a = 'hello'
>>> a[0] 
'h'
>>> a[0] = 'x'
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'str' object does not support item assignment

可变的列表:

>>> a = [1, 2, 3]
>>> id(a)
140608652166656
>>> a[0] = 'x'
>>> print(a)
['x', 2, 3]
>>> id(a)
140608652166656

不可变的元组

>>> a = (1, 2, 3)
>>> a[0]
1
>>> a[0] = 'x'
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

列表和元组

>>> l = [1, 2, 3]
>>> l.append(4)
>>> print(l)
[1, 2, 3, 4]
>>> t = (1, 2, 3)
>>> t.append(4)
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'tuple' object has no attribute 'append'

元组适合存储一组不变的数据;列表适合存储一组动态的数据。

元组中嵌套的列表是可以改变的

>>> t = (1, 2, [1, 2, 3])
>>> t[2][0] = 'x'
>>> print(t)
(1, 2, ['x', 2, 3])

运算符号

算数运算符:+ - * / // % **

赋值运算符:= += -= *= /= %= **= //=

比较(关系)运算符:== != > < >= <=

逻辑运算符:and or not

成员运算符:in not in

身份运算符:is is not

位运算符:& | ~ << >>

>>> a = 1
>>> a += a >= 1 # 相当于 a += True 所以等于是计算 a += 1
>>> print(a)
2

intfloat 类型,非 0 时被 python 认为是 True

str list tuple set dict 类型,为空时被 python 认为是 False

>>> 1 and 1
1
>>> [1] or []
[1]
>>> not 1
False

根据两个元素判断真假,第一个元素能判断出来就直接返回第一个元素,第一个元素判断不出来就返回第二个元素

>>> 1 and 0 # 都为真结果才为真,1 为真,判断不出结果,0 为假,结果为假,返回 0
0
>>> 0 and 1 # 0 为假,可以判断结果为假,不需要判断第二个元素,直接返回 0
0
>>> 1 and 2
2
>>> 2 and 1
1
>>> 1 or 0 # 有一个为真,结果就为真,1 为真直接返回 1
1
>>> 0 or 1 # 0 为假,判断不出结果,再判断 1,1 为真,结果为真,返回 1
1

字典根据 key 判断 in 或者 not in

>>> 'a' in {'a': 1}
True

== 判断值是否相等,is 判断内存地址 id 是否相等

>>> a = 1
>>> b = 1.0
>>> id(a)
140519935187248
>>> id(b)
140519935914512
>>> a == b
True
>>> a is b
False

集合无序,元组有序

>>> s1 = {1, 2, 3}
>>> s2 = {3, 2, 1}
>>> s1 == s2
True
>>> s1 is s2
False
>>> t1 = (1, 2, 3)
>>> t2 = (3, 2, 1)
>>> t1 == t2
False
>>> t1 is t2
False

判断变量的类型

>>> a = 'hello'
>>> isinstance(a, str)
True
>>> isinstance(a, int)
False
>>> isinstance(a, (str, int, float))
True
>>> isinstance(a, (int, float))
False

对象的三个特征:value id type ,判断三个特征:== is isinstance

条件与循环

条件

account = 'answer'
password = '123456'

print('please input account:')
user_account = input()
print('please input password:')
user_password = input()

if account == user_account and password == user_password:
    print('success')
else:
    print('fail')
a = input()
a = int(a)
if a == 1:
    print('apple')
elif a == 2:
    print('orange')
elif a == 3:
    print('banana')
else:
    print('shopping')

循环

counter = 0

while counter <= 10:
    counter += 1
    print(counter)
else:
    print('EOF')
a = [['apple', 'orange', 'banana'], (1, 2, 3)]
for x in a:
    for y in x:
        print(y)
else:
    print('fruit is gone')

退出所有循环

a = [1, 2, 3]
for x in a:
    if x == 2:
        break
    print(x)
1

退出本次循环

a = [1, 2, 3]
for x in a:
    if x == 2:
        continue
    print(x)
1
3
# 实现 1,3,5,7
a = [1, 2, 3, 4, 5, 6, 7, 8]
# 循环实现
for i in range(0, len(a), 2):
    print(a[i], end='|')
# 切片实现
b = a[0: len(a): 2]
print(b)

包、模块、函数与变量作用域

python 的组织结构:包->模块(.py文件)->类

当一个包被导入的时候,包中的 __init__.py 文件会自动执行

当导入一个模块的时候,就会执行这个模块的代码

c1.py

a = 2
print(a)

c2.py

import c1

执行 c2.py

python c2.py

执行结果

2

dir() 函数返回当前模块的所有变量,包括以双下划线 __ 开头结尾的模块内置变量和我们自己定义的变量

模块内置变量:

  • __package__ 返回包名,如果是入口文件,返回 NoneType 因为入口文件不属于任何包

  • __name__ 返回 包名.模块名,如果是入口文件,返回 __main__

  • __file__ 返回模块在系统中的完整路径,如果是入口文件,返回模块名执行文件时的路径,比如执行 python t/c2.py ,那么返回 t/c2.py

  • __doc__ 返回模块的文档注释

dir() 函数传入参数,返回指定模块的变量,比如 dir(sys)

-m 把入口文件当做模块执行,比如:python -m t.c2

相对导入和绝对导入

入口文件中不能使用相对导入,除非把入口文件当做模块执行

函数

认识函数

# 使用内置函数 round 保留小数点后两位
a = 3.14159
result = round(a, 2)
print(result)

函数的特点

  • 功能性
  • 隐藏细节
  • 避免编写重复的代码

函数的定义及运行特点

def funcname(parameter_list):
    pass

  1. 参数列表可以没有
  2. return 返回结果,没有 return 则返回 None
def add(x, y):
    result = x + y
    return result

def print_code(code):
    print(code)

a = add(1, 2)
b = print_code('python')

print(a, b)

执行结果

python
(3, None)

如何让函数返回多个结果

def damage(skill1, skill2):
    damage1 = skill1 * 2
    damage2 = skill2 * 3 + 1
    # 将返回一个元组
    return damage1, damage2

# 使用有意义的变量名接收返回结果
skill1_damage, skill2_damage = damage(3, 2)
print(skill1_damage, skill2_damage)

序列解包

d = 1,2,3
# d 的类型是元组
print(type(d))
# 序列解包
a,b,c = d

关键字参数

def damage(skill1, skill2):
    damage1 = skill1 * 2
    damage2 = skill2 * 3 + 1
    return damage1, damage2

# 调用函数的时候,实参使用关键字参数,代码更易读
skill1_damage, skill2_damage = damage(skill1=3, skill2=2)

可变参数

任意个数的参数

def demo(*param):
    print(type(param))
    print(param)

demo(1,2,3)

执行结果


(1, 2, 3)

使用可变参数

def sum(*param):
    sum = 0
    for i in param:
        sum += i
    print(sum)

sum(1,2,3)

执行结果

6

关键字可变参数

任意个数的关键字参数

def city_temp(**param):
    print(type(param))
    print(param)

city_temp(bj='32c', sh='36c', gz='38c')

执行结果


{'sh': '36c', 'gz': '38c', 'bj': '32c'}

使用

def city_temp(**param):
    for key,value in param.items():
        print(key, ':', value)

d = {'bj':'32c', 'sh':'36c', 'gz':'38c'}
# 如果实参是字典,加两个**
city_temp(**d)

变量作用域

每一个变量,都有它的作用范围

c = 10

def add(x, y):
    c = x + y
    print(c)

add(1, 2)
print(c)

执行结果

3
10

再看一个例子,在函数内部定义一个变量,然后在函数外部打印这个变量

def demo():
    a = 1

print(a)

在函数外部打印变量 a ,执行结果,报错

NameError: name 'a' is not defined

如果先定义一个变量,然后在函数内部引用变量,再执行函数是可以的

a = 1

def demo():
    print(a)

demo()

执行结果

1

在函数外部定义的变量,被称为全局变量;在函数内部定义的变量,被称为局部变量。

然后看一下,在循环外部,是可以引用循环内部定义的变量的

def demo():
    for i in range(0,3):
        a = 1

    print(a)

demo()

执行结果

1

作用域链

引用变量时,由内到外逐级寻找

a = 1

def func1():
    a = 2
    def func2():
        a = 3
        print(a)
    func2()

func1()

执行结果

3

注释掉 a = 3

a = 1

def func1():
    a = 2
    def func2():
        # a = 3
        print(a)
    func2()

func1()

执行结果

2

再注释掉 a = 2

a = 1

def func1():
    # a = 2
    def func2():
        # a = 3
        print(a)
    func2()

func1()

执行结果

1

global 关键字

把局部变量变成全局变量

def demo():
    global a
    a = 1

demo()
print(a)

执行结果

1

全局变量不会局限在当前模块,比如此时的变量 a ,是全局变量,那么在其他模块也是可以引用的。

面向对象

类的定义

变量名小写,单词之间使用下划线间隔

类名首字母大写,单词之间使用大写字母间隔,而不是使用下划线间隔

类下面的函数,必须有 self 参数

在函数中引用类下面的全局变量的时候,也必须加 self. 参数

class Student():
    name = '张三'
    age = 18

    def print_file(self):
        print('name: ' + self.name)
        print('age: ' + str(self.age))

使用类之前,需要先对类进行实例化

student = Student()

调用类下面的函数

student.print_file()

执行结果

name: 张三
age: 18

类最基本的作用,就是像上面这样,把变量和函数封装起来

一个模块下面可以定义多个类

定义类的模块下面只定义类,类的实例化和使用放在其他模块下面

函数与方法的区别

直接定义在模块下面的函数,称为函数;定义在类下面的函数,称为方法

直接定义在模块下面的变量,称为变量,定义在类下面的变量,称为数据成员

不必纠结函数/方法的叫法。

类与对象

类是现实世界或思维世界中的实体在计算机中的反映。它将数据(变量)以及对这些数据的操作(方法)封装在一起。

变量(数据成员)是类或对象的特征,方法是类或对象的行为。

类像模板,通过这个模板可以产生很多个不同的对象。

构造函数

类在实例化的时候,会自动调用构造函数 __init__()

构造函数除了在类实例化的时候,自动调用,也可以显示的调用,但很少这样做。

函数在没有做 return 的时候,会默认返回 None ,构造函数也一样。

构造函数可以显示的 return None ,但是不能 return 其他内容。

类变量与实例变量

类变量是和类相关的变量;实例变量是和对象相关的变量。

局部变量不会覆盖全局变量;实例变量不会覆盖类变量。

通过构造函数创建类这个模板的不同对象(实例化)

class Student():
    # 类变量
    name = '张三'
    age = 18

    # 构造函数,初始化对象的属性
    def __init__(self, name, age):
        # 实例变量
        self.name = name
        self.age = age
        
    def do_homework(self):
        print('homework')
# 实例化
student1 = Student('小明', 18)
student2 = Student('李雷', 20)
# 实例变量
print(student1.name)
print(student2.name)
# 类变量
print(Student.name)

执行结果

小明
李雷
张三

类变量定义 name 和 age 其实不合适,因为类是抽象的,不能说学生们的名字和年龄是什么,应该定义为实例变量,因为实例是具体的,可以说某个学生的姓名和年龄是什么。那类变量怎么用呢?

比如,可以创建一个类变量,用来计算一个班级的学生总人数

class Student():
    # 类变量,一个班级的学生总数
    sum = 0

    # 构造函数,初始化对象的属性
    def __init__(self, name, age):
        # 实例变量
        self.name = name
        self.age = age

类与对象的变量查找顺序

当访问一个实例变量的时候(student1.name),首先会在实例的所有变量中查找(student1.__dict__),如果没有找到,会在类变量里面查找(Student.__dict__),如果还没有的话,会到父类中查找。

self 与实例方法

实例方法:与实例相关的方法,第一个参数是 self

class Student():
    sum = 0
        # 构造函数
    def __init__(self, name, age):
        self.name = name
        self.age = age
    # 实例方法
    def do_homework(self):
        print('homework')

self 就是当前对象,比如对象 student1 调用 do_homework() 方法(student1.do_homework()),那么这时候 do_homework(self) 方法中的 self 参数,就是指的对象 student1

构造函数属于特殊的实例方法,与普通的实例方法有所不同:

  • 首先,调用方式不同
    • 调用构造函数:Student('小明', 18)
    • 调用普通实例方法:student1.do_homework()
  • 其次,作用不同
    • 构造函数用来初始化对象的属性
    • 普通实例方法用来定义对象的行为

在实例方法中访问实例变量与类变量

在实例方法中访问实例变量和类变量

class Student():
    # 类变量
    sum = 0

    # 构造函数
    def __init__(self, name, age):
        # 实例变量
        self.name = name
        self.age = age
        # 在实例方法中访问实例变量
        print(self.name)
        # 在实例方法中访问类变量的第一种方式
        print(Student.sum)
        # 在实例方法中访问类变量的第二种方式
        print(self.__class__.sum)

实例化类,自动调用构造函数

student1 = Student('小明', 18)

执行结果

小明
0
0

在实例方法中,修改类变量

class Student():
    # 类变量
    sum = 0

    # 构造函数
    def __init__(self, name, age):
        # 实例变量
        self.name = name
        self.age = age
        # 修改类变量
        Student.sum += 1
        print('当前班级学生总数是:' + str(Student.sum))

每实例化一次,就自动调用一次构造函数

student1 = Student('小明', 18)
student2 = Student('李雷', 20)
student3 = Student('小红', 17)

执行结果

当前班级学生总数是:1
当前班级学生总数是:2
当前班级学生总数是:3

类方法

类方法用于操作类相关的变量

定义类方法

  • 在方法上添加 @classmethod
  • 第一个参数 cls
class Student():
    # 类变量
    sum = 0

    # 构造函数
    def __init__(self, name, age):
        # 实例变量
        self.name = name
        self.age = age
        
    # 实例方法
    def do_homework(self):
        print('homework')
        
    # 类方法
    @classmethod
    def plus_sum(cls):
        cls.sum += 1
        print('当前班级学生总数是:' + str(cls.sum))

每创建一个对象之后,调用一次类方法

student1 = Student('小明', 18)
Student.plus_sum()
student2 = Student('李雷', 20)
Student.plus_sum()
student3 = Student('小红', 17)
Student.plus_sum()

执行结果

当前班级学生总数是:1
当前班级学生总数是:2
当前班级学生总数是:3

对象也可以调用类方法,但是不建议这么用

cls 就是当前类。Student.plus_sum() 时,plus_sum(cls) 中的 cls 就指的是类 Student

类方法不能访问实例变量

静态方法

静态方法需要在方法名上添加 @staticmethod

静态方法没有 selfcls 参数

静态方法可以被对象,也可以被类调用

静态方法不能访问实例变量

静态方法,不建议用

成员可见性:公开和私有

成员:指的是变量和方法

变量和方法的调用,都有内部调用和外部调用

class Student():
    sum = 0

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

    def do_homework(self):
        # 内部调用
        self.do_english_homework()
        print('homework')
    
    def do_english_homework(self):
        print('english homework')
student1 = Student('小明', 18)
# 外部调用
student1.do_english_homework()

有时候我们不希望变量在外部被修改,比如下面的实例变量 score

class Student():
    sum = 0

    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score

不希望像这样在外部被修改

student1 = Student('小明', 18)
student1.score = -2

所以,可以添加一个方法,专门用于操作 score

class Student():
    sum = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        # 初始化默认为 0
        self.score = 0

    def marking(self, score):
        # 判断如果传入的分数小于 0
        if score < 0:
            # 那么分数等于 0
            score = 0
        # 如果传入的分数不小于 0,那么分数就等于传入的分数
        self.score = score
        print(self.name + '同学的考试分数是:' + str(self.score))
student1 = Student('小明', 18)
student1.marking(-1)
student1.marking(59)

结果

小明同学的考试分数是:0
小明同学的考试分数是:59

所有对类下面的变量进行修改的操作,都应该由方法来完成。

但是,现在其实仍然可以通过 student1.score = -3 在外部直接赋值,因为 score 的成员可见性是公开的。

在 python 中,如果变量或方法没有以双下划线开头(只开头,不结尾),那么它的可见性就是公开的。

所以可以把 score 变成私有变量

class Student():
    sum = 0

    def __init__(self, name, age):
        self.name = name
        self.age = age
        # 私有变量
        self.__score = 0

    def marking(self, score):
        # 判断如果传入的分数小于 0
        if score < 0:
            score = 0
        # 如果传入的分数不小于 0
        self.__score = score
        print(self.name + '同学的考试分数是:' + str(self.__score))

然后在外部赋值

student1 = Student('小明', 18)
student1.__score = -1

结果:没有报错

查看对象的成员

print(student1.__dict__)

结果

{'name': '小明', 'age': 18, '_Student__score': 0, '__score': -1}

结果中值等于 0 的 _Student__score 是私有变量 __scoore ,而值等于 -1 的 __score 是在外部赋值的时候,给对象添加了一个新的变量。python 会对私有变量重新命名,以这种方式达到私有变量再被外部调用的时候不被找到,不过其实可以通过 _Student__score 来访问,所以严格的说,python 没有私有变量。

继承

继承,避免我们定义重复的变量或重复的方法。

父类

class Human:
    sum = 0
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_name(self):
        print(self.name)

子类继承父类

class Student(Human):

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

    def do_homework(self):
        print('homework')

执行

student1 = Student('小明', 18)
print(Student.sum)
print(student1.sum)
print(student1.name)
print(student1.age)
student1.get_name()

结果

0
0
小明
18
小明

在子类中,调用父类的方法

class Student(Human):

    def __init__(self, school, name, age):
        self.school = school
        # 调用父类的构造函数
        Human.__init__(self, name, age)

    def do_homework(self):
        print('homework')

执行

student1 = Student('清华大学', '小明', 18)
print(student1.school)
print(student1.name)
print(student1.age)

结果

清华大学
小明
18

上面这样在子类的中调用父类的方法的方式,虽然可以,但是有问题,Human.__init__(self, name, age) 是在用类,调用实例方法

所以,调用父类的方法需要使用 super() 函数:

  • super(当前类名, self).要调用的父类当中的方法名(参数)

父类

class Human:
    sum = 0
    
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_name(self):
        print(self.name)
    
    def do_homework(self):
        print('这是父类中的 do_homework 方法')

子类

class Student(Human):

    def __init__(self, school, name, age):
        self.school = school
        # 调用父类的构造函数
        super(Student, self).__init__(name, age)

    def do_homework(self):
        # 调用父类中的 do_homework 方法
        super(Student, self).do_homework()
        print('这是子类中的 do_homework 方法')

执行

student1 = Student('清华大学', '小明', 18)
student1.do_homework()

结果

这是父类中的 do_homework 方法
这是子类中的 do_homework 方法

你可能感兴趣的:(数据类型、函数、面向对象)