Python面向对象(上)

前置知识点介绍

1 变量

1.1 Python的变量类型

变量存储在内存中的值,这就意味着在创建变量时会在内存中创建一个地址。基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中。因此,变量可以指定不同的数据类型,这些变量可以存储整数,浮点数或字符串等。

1.2 变量赋值

Python 中的变量赋值不需要声明类型。每个变量在内存中创建,都包括变量的标识,名称和数据这些信息。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。等号=用来给变量赋值。

等号运算符左边是变量名,等号=运算符右边是存储在变量中的值。例如:

In [1]

int_test = 100  # 整型
float_test = 100.0  # 浮点型
name = "James"  # 字符串

print(int_test, type(int_test))
print(float_test, type(float_test))
print(name, type(name))
100 <class 'int'>
100.0 <class 'float'>
James <class 'str'>

Python中也允许同时对多变量进行赋值,例如:

In [2]

a, b, c = 1, 2.0, "3.0"
print(a, type(a), b, type(b), c, type(c))
1 <class 'int'> 2.0 <class 'float'> 3.0 <class 'str'>

2 命名空间

定义: 命名空间(Namespace)是从名称到对象的映射,大部分的命名空间都是通过 Python 字典来实现的。

作用: 命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何联系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名,但建议在实际编程过程中尽量避免重名的情况。

说明: 一般有三种形式的命名空间。

  • 内置命名空间(Built-in names): 用于存放Python 的内置函数的空间,比如,print,input等不需要定义即可使用的函数就处在内置命名空间。
  • 全局命名空间(Global names):模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部命名空间(Local names):函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。在函数内定义的局部变量,在函数执行结束后就会失效,即无法在函数外直接调用函数内定义的变量。

命名空间查找顺序: 局部命名空间→全局命名空间→内置命名空间。

命名空间的生命周期: 命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。

举例: 通过下面这个例子来试着理解一下上述三种命名空间吧。

In [3]

# 在全局命名空间中给变量a赋值,令a=1。
a = 1

# 在定义函数“function1”的同时就为其创建了一个独立的局部命名空间。
def function1():
    # 变量b在局部命名空间中被赋值“a+1”。
    b = a + 1
    # 此处所使用的print函数就是源自Python的内置命名空间。
    print(b)
    
# 执行function1时,计算机会优先找到function1局部命名空间中的“b=a+1”,然后再找到全局命名空间中的“a=1”,最后找到内置命名空间中的print将b的值打印出来。
function1()   
2

3 作用域

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:

  • Local:在程序的最内层,包含局部变量,比如,一个函数的内部。
  • Enclosing:包含了非局部(non-local)也非全局(non-global)的变量。比如,两个嵌套函数,函数(或类)A里面又包含了函数B,那么对于B中的名称来说 A中的作用域就为no-nlocal。
  • Global:当前脚本的最外层,比如,当前模块的全局变量。
  • Built-in: 包含了内建的变量/关键字等,比如,int。

4 异常

4.1 什么是异常?

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。一般情况下,在Python无法正常处理程序时就会发生一个异常。异常是Python对象,表示一个错误。当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

4.2 异常处理

捕捉异常可以使用try/except语句。try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。如果你不想在异常发生时结束你的程序,只需在try里捕获它。

说明:

try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到这里,try子句先执行,接下来会发生什么依赖于执行时是否出现异常。

  • 如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句,异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。
  • 如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印默认的出错信息)。
  • 如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。

语法:

try:
	语句        # 正常的操作。
except name:
	语句        # 如果在try部份触发了'name'异常,执行这块代码。
except name,数据:
	语句        # 如果触发了'name'异常,获得附加的数据,执行这块代码。
else:
	语句        # 如果没有异常执行这块代码
finally:
	语句        # 无论有没有异常都会执行

举例:

In [61]

list1 = [1,2,3,4,'5',6,7,8]
list2 = []
for i in range(len(list1)):
    try:
        list1[i]+=1
        list2.append(list1[i])
        print(list2)
    except:
        print('有异常发生')
[2]
[2, 3]
[2, 3, 4]
[2, 3, 4, 5]
有异常发生
[2, 3, 4, 5, 7]
[2, 3, 4, 5, 7, 8]
[2, 3, 4, 5, 7, 8, 9]
  • Tip: 关于异常更为详细的介绍可参考课节2课件里面的“异常与错误处理”

  • 地址: https://aistudio.baidu.com/aistudio/projectdetail/1516473

5 sorted函数

Python中sorted()函数可对所有可迭代的对象进行排序操作。

Tip:sort与sorted区别:

sort是应用在list上的方法,sorted可以对所有可迭代的对象进行排序操作。

list的sort方法返回的是对已经存在的列表进行操作,而内建函数sorted方法返回的是一个新的list,而不是在原来的基础上进行的操作。

语法:

sorted(iterable, key=None, reverse=False)
# iterable:可迭代对象。
# key:主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
# reverse:排序规则,reverse = True 降序 , reverse = False 升序(默认)。

举例:

  1. 对list进行排序。

In [4]

# 定义一个由0-7乱序组成的“test_list”。
test_list = [5, 7, 0, 6, 4, 2, 1, 3]

# 使用sorted()函数对“test_list”进行排序。
result_list1 = sorted(test_list)
result_list2 = sorted(test_list, reverse=True)
result_list3 = sorted(test_list, key=lambda x: x * -1)

# 打印、查看并理解三种排序的结果。
print(result_list1, result_list2, result_list3)
[0, 1, 2, 3, 4, 5, 6, 7] [7, 6, 5, 4, 3, 2, 1, 0] [7, 6, 5, 4, 3, 2, 1, 0]
  1. 对字典进行排序。

In [5]

# 定义一个乱序的key值为0-5,value值为A-E的字典。
test_dict = {4: 'D', 2: 'B', 1: 'A', 5: 'E', 3: 'C'}

# 使用sorte()函数对“test_dict”进行排序,打印排序的结果。
print(sorted(test_dict))
print(sorted(test_dict, reverse=True))
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]

6 pop函数

Python中pop()函数可用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。

语法:

list.pop([index])
# index:index为可选参数,用于表示要移除列表元素的索引值,不能超过列表总长度,默认为index值为“-1”,即删除列表中的最后一个值。

举例:

In [7]

# 定义一个由0-7组成的list。
numbers = [0, 1, 2, 3, 4, 5, 6, 7]
# 对list使用pop()函数,查看pop()的返回值以及pop()之后的list。
print(numbers.pop(), numbers)
7 [0, 1, 2, 3, 4, 5, 6]

In [8]

# 定义一个由0-7组成的list。
numbers = [0, 1, 2, 3, 4, 5, 6, 7]
# 对list使用pop(2)函数,查看pop(2)的返回值以及pop(2)之后的list。
print(numbers.pop(2), numbers)
2 [0, 1, 3, 4, 5, 6, 7]

7 id函数

Python中id()函数可返回对象的唯一标识符,标识符是一个整数。CPython 中id()可用于获取对象的内存地址。

语法:

id(object)
# object:需要获取标识符的对象。

举例:

In [38]

# 定义变量a,b,c。
a = 1
b = 2.0
c = '3.0'

# 查看变量a,b,c的标识符及变量类型。
print(id(a), type(a))
print(id(b), type(b))
print(id(c), type(c))
94219067450144 <class 'int'>
140242766393936 <class 'float'>
140242505218608 <class 'str'>

8 dir函数

Python中dir()函数不带参数时,可返回当前范围内的变量、方法和定义的类型列表;带参数时,可返回参数的属性、方法列表。如果参数包含方法dir(),该方法将被调用。如果参数不包含dir(),该方法将最大限度地收集参数信息。

语法:

dir(object)
# object:对象、变量、类型。

举例:

In [40]

dir(list)
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'append',
 'clear',
 'copy',
 'count',
 'extend',
 'index',
 'insert',
 'pop',
 'remove',
 'reverse',
 'sort']

9 split函数

Python中split()函数可通过指定分隔符对字符串进行分割,如果参数num有指定值,则分隔num+1个子字符串。

语法:

str.split("sign", num)
# sign:分隔符,用于指定对字符串进行分割的单位,常见的分隔符有空格、逗号等。
# num:分割次数,需要注意的是,分割之后的字符串个数等于分割次数加一。

举例:

In [41]

# 定义一个中间有两个空格的字符串。
str = "abc def ghi"

# 查看并对比使用split()函数之后,str的变化。
print(str, str.split(" "), str.split(" ", 1))
abc def ghi ['abc', 'def', 'ghi'] ['abc', 'def ghi']

10 help函数

Python中help()函数可用于查看函数或模块用途的详细说明。help()函数相当于一个内置的Python帮助手册,当我们遇到一些新的函数名称时,掌握好help()函数的使用可以让我们更快更清晰地理解Python里面这些新函数的作用。

语法:

help(object)
# object:需要查看详细说明信息的对象。

举例:

In [46]

# 查看Python常用的内置函数的help信息,此处为查看关于str的详细说明。
help('str')

In [45]

# 查看自定义列表“my_list”的help信息。此处查看list的详细说明,也可以直接用 help('list')
my_list = ['a', 'b', 'c', 'd', 'e']
help(my_list)

In [47]

# 查看作用于自定义列表的内置函数的help信息。此处查看appdend()函数的详细说明,也可以直接用 help(list.append)
my_list = ['a', 'b', 'c', 'd', 'e']
help(my_list.append)

In [51]

# 查看一些package的help()信息,比如下面代码可查看正则表达式详细说明,需要注意的是package名称外面要加英文状态下的单引号或双引号,也可以用 help("re")
help('re')

11 threading模块

threading,基于线程的并行,这个模块在较低级的模块 _thread (底层多线程 API)基础上建立较高级的线程接口。

该模块定义了以下函数:

threading.active_count() 返回当前存活的线程类 Thread 对象。返回的计数等于 enumerate() 返回的列表长度。

threading.current_thread() 返回当前对应调用者的控制线程的 Thread 对象。如果调用者的控制线程不是利用 threading 创建,会返回一个功能受限的虚拟线程对象。

threading.get_ident() 返回当前线程的 “线程标识符”。它是一个非零的整数。它的值没有直接含义,主要是用作 magic cookie,比如作为含有线程相关数据的字典的索引。线程标识符可能会在线程退出,新线程创建时被复用。

更多关于threading的详细说明,可前往Python官网文档查看,地址如下:

https://docs.python.org/zh-cn/3.7/library/threading.html

12 zipfile模块

ZIP 文件格式是一个常用的归档与压缩标准。 这个模块提供了创建、读取、写入、添加及列出 ZIP 文件的工具。 任何对此模块的进阶使用都将需要理解此格式,其定义参见 PKZIP 应用程序笔记。

此模块目前不能处理分卷 ZIP 文件。它可以处理使用 ZIP64 扩展(超过 4 GB 的 ZIP 文件)的 ZIP 文件。它支持解密 ZIP 归档中的加密文件,但是目前不能创建一个加密的文件。解密非常慢,因为它是使用原生 Python 而不是 C 实现的。

下面展示一下zipfile的几个常用函数:

ZipFile.close() 关闭归档文件。 你必须在退出程序之前调用 close() 否则将不会写入关键记录数据。

ZipFile.getinfo(name) 返回一个 ZipInfo 对象,其中包含有关归档成员 name 的信息。 针对一个目前并不包含于归档中的名称调用 getinfo() 将会引发 KeyError。

ZipFile.infolist() 返回一个列表,其中包含每个归档成员的 ZipInfo 对象。 如果是打开一个现有归档则这些对象的排列顺序与它们对应条目在磁盘上的实际 ZIP 文件中的顺序一致。

ZipFile.namelist() 返回按名称排序的归档成员列表。

*ZipFile.open(name, mode='r', pwd=None, , force_zip64=False) 以二进制文件类对象的形式访问一个归档成员。 name 可以是归档内某个文件的名称也可以是某个 ZipInfo 对象。 如果包含了 mode 形参,则它必须为 'r' (默认值) 或 'w'。 pwd 为用于解密已加密 ZIP 文件的密码。

更多关于zipfile的详细说明,可前往Python官网文档查看,地址如下:

https://docs.python.org/zh-cn/3.7/library/zipfile.html

 

需求:选手的最好的三次成绩

Kelly教练每天在训练场忙的焦头烂额,根本没有时间摆弄计算机,需要人帮他处理选手的数据!

运动员在刻苦训练,每跑一个600米,kelly就会计时并将时间记录到计算机中的文本文件中,共有4个选手James、Sarah、Julie和Mikey,分别对应4个文件

james.txt 2-34,3:21,2,34,2.45,3.01,2:01,2:01,3:10,2-22

sarah.txt 2:58,2.58,2:39,2-25,2:55,2:54,2.18,2:55,2:55

julie.txt 2.59,2.11,2:11,2:23,3-10,2-23,3:10,3.21,3-21

mikey.txt 2:22,3.01,3:01,3.02,3:02,3.02,3:22,2.49,2:38

In [1]

# 读取文件内容,按逗号进行切分
def get_coach_data(filename):
    with open(filename) as f:
        line = f.readline()
    return line.strip().split(',')

# 输出读取文件的结果
times = get_coach_data('mywork/james.txt')
print('读取文件james.txt后的结果:\n')
print(times)
读取文件james.txt后的结果:

['2-34', '3:21', '2', '34', '2.45', '3.01', '2:01', '2:01', '3:10', '2-22']

get_coach_data函数的说明:

  • filename为文件路径

  • f表示文件对象

  • f.realine()表示读取文件的一行

  • line.strip().split(',')为链式函数写法意思是,先对这一行的数据进行strip(),就是去掉改行头尾空格和换行符。然后对strip()的结果进行split(','),对结果以逗号的进行切分形成一个数组。

In [2]

# 数据格式标准化
def sanitize(time_string):
    if '-' in time_string:
        splitter = '-'
    elif ':' in time_string:
        splitter = ':'
    else:
        return (time_string)
    (mins,secs) = time_string.split(splitter)
    return (mins+'.'+secs)

sanitize函数的说明:

  • time_string为时间数组

  • splitter是根据原数据的格式来确实分钟和秒的分隔符

  • (mins,secs) = time_string.split(splitter)以splitter分隔符切分每个时间数据到两个变量中mins,secs

  • return (mins+'.'+secs)将分钟和秒以字符串点进行连接

In [3]

# 输出数据格式标准化后的时间
james_times = get_coach_data('mywork/james.txt')
clean_james = []
for each_t in james_times:
    clean_james.append(sanitize(each_t))
print('输出james.txt标准化后的结果\n')
print(clean_james)
输出james.txt标准化后的结果

['2.34', '3.21', '2', '34', '2.45', '3.01', '2.01', '2.01', '3.10', '2.22']

In [4]

# 排序
sorted_james=sorted(clean_james)

# 去掉重复
unique_james = []
for each_t in sorted_james:
    if each_t not in unique_james:
        unique_james.append(each_t)

print('输出排序并去重后的结果,并取前3个数据\n')
print(unique_james[0:3])
输出排序并去重后的结果,并取前3个数据

['2', '2.01', '2.22']

In [5]

# python,一句话搞定数据标准化,排序和去重
james_times = get_coach_data('mywork/james.txt')
print('一句话搞定数据标准化、排序、去重\n')
print(sorted(set([sanitize(t) for t in james_times]))[0:3])
一句话搞定数据标准化、排序、去重

['2', '2.01', '2.22']

问题:哪个数据属于哪个选手

解决:kelly人为他有办法,他为数据增加了标识(在原来的数据前面增加了姓名和生日)

james,2006-11-11,2-34,3:21,2.34,2.45,3.01,2:01,2:01,3:10,2-22

In [6]

# 读取新的数据文件
james_new = get_coach_data('mywork/james_new.txt')
(james_name,james_dob) = james_new.pop(0),james_new.pop(0)
james_top3 = sorted(set([sanitize(t) for t in james_new]))[0:3]
print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james_name,james_dob,james_top3))
姓名:james,生日:2006-11-11,最快的3次成绩:['2.01', '2.22', '2.34']

pop函数:

james_new.pop(0)移除列表中的第一个数据,并获得删除的数据

弹夹

问题:james一个人的数据需要3个变量存储,如果是4个人的话?

In [7]

james_new = get_coach_data('mywork/james_new.txt')
mikey_new = get_coach_data('mywork/mikey_new.txt')
julie_new = get_coach_data('mywork/julie_new.txt')
sarah_new = get_coach_data('mywork/sarah_new.txt')

(james_name,james_dob) = james_new.pop(0),james_new.pop(0)
james_top3 = sorted(set([sanitize(t) for t in james_new]))[0:3]

print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james_name,james_dob,james_top3))

(mikey_name,mikey_dob) = mikey_new.pop(0),mikey_new.pop(0)
mikey_top3 = sorted(set([sanitize(t) for t in mikey_new]))[0:3]

print('姓名:%s,生日:%s,最快的3次成绩:%s' %(mikey_name,mikey_dob,mikey_top3))

(julie_name,julie_dob) = julie_new.pop(0),julie_new.pop(0)
julie_top3 = sorted(set([sanitize(t) for t in julie_new]))[0:3]

print('姓名:%s,生日:%s,最快的3次成绩:%s' %(julie_name,julie_dob,julie_top3))


(sarah_name,sarah_dob) = sarah_new.pop(0),sarah_new.pop(0)
sarah_top3 = sorted(set([sanitize(t) for t in sarah_new]))[0:3]

print('姓名:%s,生日:%s,最快的3次成绩:%s' %(sarah_name,sarah_dob,sarah_top3))
姓名:james,生日:2006-11-11,最快的3次成绩:['2.01', '2.22', '2.34']
姓名:mikey,生日:2003-9-10,最快的3次成绩:['2.22', '2.38', '2.49']
姓名:julie,生日:2006-5-9,最快的3次成绩:['2.11', '2.23', '2.59']
姓名:sarah,生日:2004-3-8,最快的3次成绩:['2.18', '2.25', '2.39']

使用字典将变量变少

In [8]

james_new = get_coach_data('mywork/james_new.txt')

james_data={}

james_data['Name'] = james_new.pop(0)
james_data['Dob'] = james_new.pop(0)
james_data['top3'] = sorted(set([sanitize(t) for t in james_new]))[0:3]

print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james_data['Name'],james_data['Dob'],james_data['top3']))

姓名:james,生日:2006-11-11,最快的3次成绩:['2.01', '2.22', '2.34']

问题:即使有字典的帮助还不能完美的解决问题,函数与数据并没有直接联系,分散在源文件中,不利于代码的维护

In [9]

class Athlete:
    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.name = a_name
        self.dob = a_dob
        self.times = a_times

    def top3(self):
        return sorted(set([sanitize(t) for t in self.times]))[0:3]
        
    def sanitize(self,time_string):
        if '-' in time_string:
            splitter = '-'
        elif ':' in time_string:
            splitter = ':'
        else:
            return (time_string)
        (mins,secs) = time_string.split(splitter)
        return (mins+'.'+secs)

使用类的好处

  1. 降低复杂性-》更少的bug-》提高可维护行

  2. 类可以将数据与函数绑定在一起,使代码模块化

  3. 调用数据和函数,使用对象名.的方式,使代码更加优雅

In [10]

# 从文件中读取数据
james_new = get_coach_data('mywork/james_new.txt')
james_name = james_new.pop(0)
james_dob = james_new.pop(0)
james_times = james_new

# 创建Athlete对象
james = Athlete(james_name,james_dob,james_times)
print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james.name,james.dob,james.top3()))
姓名:james,生日:2006-11-11,最快的3次成绩:['2.01', '2.22', '2.34']

面向对象的世界

代码通常称为类的方法,数据通常称为类的属性,实例化的对象称为实例

In [11]

class Athlete:
    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.name = a_name
        self.dob = a_dob
        self.times = a_times

    def top3(self):
        return sorted(set([self.sanitize(t) for t in self.times]))[0:3]
        
    def sanitize(self,time_string):
        if '-' in time_string:
            splitter = '-'
        elif ':' in time_string:
            splitter = ':'
        else:
            return (time_string)
        (mins,secs) = time_string.split(splitter)
        return (mins+'.'+secs)

如何定义类

class Athlete:

  • 第一部分:class定义类的关键字,Athlete符合python标识符命名规则,:表示类内容的开始

def init(self,a_name,a_dob=None,a_times=[]):

  • 第二部分:def定义函数的关键字,init 方法是一个特殊方法会在实例化对象时自动调用,我们会在这个方法中对数据进行赋值。self作为类中函数的第一个参数,方便该方法调用该类的其他属性和方法。

  • 第三部分:自定义的属性和方法

In [12]

def get_coach_data(filename):
    with open(filename) as f:
        line = f.readline()
    return line.strip().split(',')

# 从文件中读取数据
james_new = get_coach_data('mywork/james_new.txt')
james_name = james_new.pop(0)
james_dob = james_new.pop(0)
james_times = james_new

# 创建Athlete对象
james = Athlete(james_name,james_dob,james_times)

print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james.name,james.dob,james.top3()))
姓名:james,生日:2006-11-11,最快的3次成绩:['2.01', '2.22', '2.34']

如何使用类

1.创建对象

对象名 = 类名(参数)

2.使用.调用类的方法和属性

对象.属性名

对象.方法名()

类属性

所有对象共享的数据

In [13]

class Athlete:

    #运动员集训了,要买东西的同学要把地址改一下
    address = '中国足球协会训练基地xx街xx号'

    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.name = a_name
        self.dob = a_dob
        self.times = a_times

    def top3(self):
        return sorted(set([self.sanitize(t) for t in self.times]))[0:3]
        
    def sanitize(self,time_string):
        if '-' in time_string:
            splitter = '-'
        elif ':' in time_string:
            splitter = ':'
        else:
            return (time_string)
        (mins,secs) = time_string.split(splitter)
        return (mins+'.'+secs)

In [14]

julie_new = get_coach_data('mywork/julie_new.txt')
julie_name = julie_new.pop(0)
julie_dob = julie_new.pop(0)
julie_times = julie_new

james_new = get_coach_data('mywork/james_new.txt')
james_name = james_new.pop(0)
james_dob = james_new.pop(0)
james_times = james_new

julie = Athlete(julie_name,julie_dob,julie_times)
james = Athlete(james_name,james_dob,james_times)

print(julie.address)
print(james.address)
print(Athlete.address)
中国足球协会训练基地xx街xx号
中国足球协会训练基地xx街xx号
中国足球协会训练基地xx街xx号

如何使用:

定义:

在 init 之上,或者说在类的范围内与方法同等级别,书写变量名=值

调用:

类名.类属性

类方法

所有对象共享的方法

In [15]

class Athlete:

    #运动员集训了,要买东西的同学要把地址改一下
    address = '中国足球协会训练基地xx街xx号'

    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.name = a_name
        self.dob = a_dob
        self.times = a_times

    def top3(self):
        return sorted(set([self.sanitize(t) for t in self.times]))[0:3]
        
    def sanitize(self,time_string):
        if '-' in time_string:
            splitter = '-'
        elif ':' in time_string:
            splitter = ':'
        else:
            return (time_string)
        (mins,secs) = time_string.split(splitter)
        return (mins+'.'+secs)
    @classmethod
    def changeAddress(self):
        self.address = '中国田径训练基地xx街xx号'
     

In [16]

#集训队换地方了
Athlete.changeAddress()
print(julie.address)
print(james.address)
print(Athlete.address)
中国足球协会训练基地xx街xx号
中国足球协会训练基地xx街xx号
中国田径训练基地xx街xx号

如何使用:

定义:

方法定义时,使用@classmethod标记

调用:

类名.类方法

对象.类方法

In [17]

class Athlete:
    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.name = a_name
        self.dob = a_dob
        self.times = a_times

    def top3(self):
        return sorted(set([self.sanitize(t) for t in self.times]))[0:3]
        
    def sanitize(self,time_string):
        if '-' in time_string:
            splitter = '-'
        elif ':' in time_string:
            splitter = ':'
        else:
            return (time_string)
        (mins,secs) = time_string.split(splitter)
        return (mins+'.'+secs)

In [18]

james = Athlete(james_name,james_dob,james_times)
james.name = 'hehe'
# james.sanitize()
print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james.name,james.dob,james.top3()))
姓名:hehe,生日:2006-11-11,最快的3次成绩:['2.01', '2.22', '2.34']

sanitize()函数,直接调用的话,不知道有什么用呢?

sanitize()函数是在Athlete中,专门用来处理将训练的时间进行标准化的,干脆把它声明为私用的,不会用的话干脆让你看不到就行了。

james.name = 'hehe'你不可以这样啊,怎么可以直接改呢! 干脆不让你改

In [19]

class Athlete:
    def __init__(self,a_name,a_dob=None,a_times=[]):
        self.__name = a_name
        self.dob = a_dob
        self.times = a_times
       
    def sayName(self):
        print(self.__name)
        
    def top3(self):
        return sorted(set([self.__sanitize(t) for t in self.times]))[0:3]
        
    def __sanitize(self,time_string):
        if '-' in time_string:
            splitter = '-'
        elif ':' in time_string:
            splitter = ':'
        else:
            return (time_string)
        (mins,secs) = time_string.split(splitter)
        return (mins+'.'+secs)

In [20]

james = Athlete(james_name,james_dob,james_times)
# print(james._name)
# james.__sanitize()
print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james.name,james.dob,james.top3()))

---------------------------------------------------------------------------AttributeError Traceback (most recent call last)<ipython-input-20-e9b511a878b8> in <module> 2 # print(james._name) 3 # james.__sanitize() ----> 4 print('姓名:%s,生日:%s,最快的3次成绩:%s' %(james.name,james.dob,james.top3())) AttributeError: 'Athlete' object has no attribute 'name'

私用的属性和方法的定义:

在属性和方法名前加 __ 两个下划线

如何调用:

只能通过类中的方法来调用私有的属性和方法

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python面向对象编程是一种编程范式,它将程序组织成对象的集合,每个对象都有自己的属性和方法。在Python中,可以通过定义类来创建对象,并通过实例化类来创建具体的对象。引用[1]中的代码示例展示了一个Animal类,其中包含了初始化方法和一个__str__方法来返回对象的描述信息。通过这个类,可以创建Animal对象,并通过print函数输出对象。引用中的代码示例展示了如何使用@property装饰器来定义类的属性和属性的访问方法。通过这种方式,可以在访问属性时像访问普通属性一样使用点号,而不需要使用方法调用的方式。引用中的代码示例展示了多态在Python中的应用。多态是面向对象编程的重要概念,它允许不同的对象以相同的方式对外部访问,但具体的实现可能不同。在这个示例中,father、son和daughter类都继承了father类,并重写了tell方法。通过调用不同的对象的tell方法,可以看到不同的输出结果。总之,Python面向对象编程是一种灵活且强大的编程方式,它允许开发者以对象为中心来思考和组织代码,提高了代码的可读性和可维护性。通过定义类、创建对象和使用类的属性和方法,可以实现丰富多样的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Python面向对象(全套)](https://blog.csdn.net/Thewei666/article/details/126652501)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身在江湖的郭大侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值