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

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)
<class 'int'>
>>> type(1*1.0)
<class 'float'>
>>> type(2/2)
<class 'float'>
>>> type(2//2)
<class 'int'>
>>> type(True)
<class 'bool'>
>>> type(False)
<class 'bool'>
>>> 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))
<class 'tuple'>
>>> type((1))
<class 'int'>
>>> type(('hello'))
<class 'str'>

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

>>> type((1,))
<class 'tuple'>

定义空元组

>>> type(())
<class 'tuple'>

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

集合 set

定义集合

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

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

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

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

>>> {1, 2, 3}[-2:]
<stdin>:1: SyntaxWarning: 'set' object is not subscriptable; perhaps you missed a comma?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
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({})
<class 'dict'>
>>> type(set())
<class '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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
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 "<stdin>", line 1, in <module>
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)

执行结果

<type 'tuple'>
(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')

执行结果

<type 'dict'>
{'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 方法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容

  • 定义类并创建实例 在Python中,类通过 class 关键字定义。以 Person 为例,定义一个Person类...
    绩重KF阅读 3,879评论 0 13
  • 〇、前言 本文共108张图,流量党请慎重! 历时1个半月,我把自己学习Python基础知识的框架详细梳理了一遍。 ...
    Raxxie阅读 18,787评论 17 410
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,680评论 1 10
  • python基础 1.字符串和编码对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr(...
    jxxh阅读 471评论 0 0
  • 一、快捷键 ctr+b 执行ctr+/ 单行注释ctr+c ...
    o_8319阅读 5,728评论 2 16