pythonmainoffset_python之(22)基础总结(5)

1、Python3 面向对象

1.面向对象技术简介

类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

方法:类中定义的函数。

类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。

方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。

局部变量:定义在方法中的变量,只作用于当前实例的类。

实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。

继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。

实例化:创建一个类的实例,类的具体对象。

对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。

Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。

对象可以包含任意数量和类型的数据。

2.类定义

类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。

3、类对象

类对象支持两种操作:属性引用和实例化。

属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name。

4、类的方法

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

注意:def__init__(self,...........):是构造方法

#类定义

classpeople:#定义基本属性

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

__weight =0#定义构造方法

def __init__(self, n, a, w):

self.name=n

self.age=a

self.__weight =wdefspeak(self):print("%s说:我已经%d岁了,体重%d斤" % (self.name, self.age, self.__weight))#实例化类

p = people('rancor', 10, 30)

p.speak()

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

rancor说:我已经10岁了,体重30斤

Process finished with exit code 0

5、继承

①单继承

class DerivedClassName(modname.BaseClassName):

测试:

#!/usr/bin/python3

#类定义

classpeople:#定义基本属性

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

__weight =0#定义构造方法

def __init__(self, n, a, w):

self.name=n

self.age=a

self.__weight =wdefspeak(self):print("%s 说: 我 %d 岁。" %(self.name, self.age))#单继承示例

classstudent(people):

grade= ''

def __init__(self, n, a, w, g):#调用父类的构函

people.__init__(self, n, a, w)

self.grade=g#覆写父类的方法

defspeak(self):print("%s 说: 我 %d 岁了,体重%d斤,我在读 %d 年级" %(self.name, self.age, self.grade))

s= student('ken', 10, 60, 3)

s.speak()

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

ken 说: 我10 岁了,我在读 3年级

Process finished with exit code 0

注意:私有属性的定义是:_+属性名(_weight),其中私有属性不能被子类所访问

②多继承

class sample(speaker, student):

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

方法名同,默认调用的是在括号中排前面的父类的方法

①父类中有相同的方法名时:

#!/usr/bin/python3

#类定义

classpeople:#定义基本属性

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

__weight =0#定义构造方法

def __init__(self, n, a, w):

self.name=n

self.age=a

self.__weight =wdefspeak(self):print("%s 说: 我 %d 岁。" %(self.name, self.age))#单继承示例

classstudent(people):

grade= ''

def __init__(self, n, a, w, g):#调用父类的构函

people.__init__(self, n, a, w)

self.grade=g#覆写父类的方法

defspeak(self):print("%s 说: 我 %d 岁了,我在读 %d 年级" %(self.name, self.age, self.grade))#另一个类,多重继承之前的准备

classspeaker():

topic= ''name= ''

def __init__(self, n, t):

self.name=n

self.topic=tdefspeak(self):print("我叫 %s,我是一个演说家,我演讲的主题是 %s" %(self.name, self.topic))#多重继承

classsample(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()#方法名同,默认调用的是在括号中排前地父类的方法

②父类中不存在相同的方法名

#!/usr/bin/python3

#类定义

classpeople:#定义基本属性

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

__weight =0#定义构造方法

def __init__(self, n, a, w):

self.name=n

self.age=a

self.__weight =wdefspeak(self):print("%s 说: 我 %d 岁。" %(self.name, self.age))#单继承示例

classstudent(people):

grade= ''

def __init__(self, n, a, w, g):#调用父类的构函

people.__init__(self, n, a, w)

self.grade=g#覆写父类的方法

defspeak(self):print("%s 说: 我 %d 岁了,我在读 %d 年级" %(self.name, self.age, self.grade))#另一个类,多重继承之前的准备

classspeaker:

topic= ''name= ''

def __init__(self, n, t):

self.name=n

self.topic=tdefspeak1(self):print("我叫 %s,我是一个演说家,我演讲的主题是 %s" %(self.name, self.topic))#多重继承

classsample(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()#方法名同,默认调用的是在括号中排前面的父类的方法

test.speak1()

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

Tim 说: 我25 岁了,我在读 4年级

我叫 Tim,我是一个演说家,我演讲的主题是 Python

Process finished with exit code 0

6、方法重写

如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,其中super() 函数是用于调用父类(超类)的一个方法

classpeople:

name= ''sex= ''age=0#私有化ID卡

_telPhone = ''

#定义构造方法

def __init__(self, n, s, a, telPhone):

self.name=n;

self.sex=s;

self.age=a;

self._telPhone=telPhonedefshow(self):print("我是%s,性别%s,年龄%d岁,手机号是%s" %(self.name, self.sex, self.age, self._telPhone))#单继承

classstudent(people):

grade= ''

def __init__(self, n, s, a, telPhone, g):

people.__init__(self, n, s, a, telPhone)

self.grade=gdefshow(self):print("我是%s,性别%s,年龄%d岁,在读%s年级" %(self.name, self.sex, self.age, self.grade))#注意实例化类一定得有()

s = student('ruboo', '男', 12, '12345678910', '三')

s.show()

super(student, s).show()

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

我是ruboo,性别男,年龄12岁,在读三年级

我是ruboo,性别男,年龄12岁,手机号是12345678910

Process finished with exit code 0

注意:实例化类一定得加()。调用方法时方法也得加()

7、类的属性和方法

类的私有属性

__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。

类的方法

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

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

类的私有方法

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

注意实例化不能访问私有属性和私有方法,不过可以通过在本类中非私有化的方法是调用类的私有属性或者私有方法再进行实例化访问

8、类的专有方法

__init__ : 构造函数,在生成对象时调用

__del__ : 析构函数,释放对象时使用

__repr__ : 打印,转换

__setitem__ : 按照索引赋值

__getitem__: 按照索引获取值

__len__: 获得长度

__cmp__: 比较运算

__call__: 函数调用

__add__: 加运算

__sub__: 减运算

__mul__: 乘运算

__truediv__: 除运算

__mod__: 求余运算

__pow__: 乘方

9、运算符重载

实现两两数求加减乘除

classVector:def __init__(self, a, b):

self.a=a

self.b=b#重载字符串函数

def __str__(self):return 'Vector (%d, %d)' %(self.a, self.b)#重载加法运算符

def __add__(self, other):return Vector(self.a + other.a, self.b +other.b)#重载减法运算符

def __sub__(self, other):return Vector(self.a - other.a, self.b -self.b)#重载乘法运算符

def __mul__(self, other):return Vector(self.a * other.a, self.a *self.b)#重载除法运算符

def __truediv__(self, other):return Vector(self.a / other.a, self.b /other.b)

v1= Vector(20, 10)

v2= Vector(5, 2)print(v1 +v2)print(v1 -v2)print(v1 *v2)print(v1 / v2)

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

Vector (25, 12)

Vector (15, 0)

Vector (100, 200)

Vector (4, 5)

Process finished with exit code 0

2、Python3 命名空间和作用域

1、命名空间

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

命名空间提供了在项目中避免名字冲突的一种方法。各个命名空间是独立的,没有任何关系的,所以一个命名空间中不能有重名,但不同的命名空间是可以重名而没有任何影响。

我们举一个计算机系统中的例子,一个文件夹(目录)中可以包含多个文件夹,每个文件夹中不能有相同的文件名,但不同文件夹中的文件可以重名。

0129A8E9-30FE-431D-8C48-399EA4841E9D.jpg

一般有三种命名空间:

内置名称(built-in names), Python 语言内置的名称,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。

全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。

局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)

types_namespace-1.png

命名空间查找顺序:

假设我们要使用变量 runoob,则 Python 的查找顺序为:局部的命名空间去 -> 全局命名空间 -> 内置命名空间。

如果找不到变量 runoob,它将放弃查找并引发一个 NameError 异常:

命名空间的生命周期:

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

因此,我们无法从外部命名空间访问内部命名空间的对象。

相同的对象名称可以存在于多个命名空间中。

namespaces.png

#var1 是全局名称

var1 = 5

defsome_func():#var2 是局部名称

var2 = 6

defsome_inner_func():#var3 是内嵌的局部名称

var3 = 7

2、作用域

作用域就是一个 Python 程序可以直接访问命名空间的正文区域。

在一个 python 程序中,直接访问一个变量,会从内到外依次访问所有的作用域直到找到,否则会报未定义的错误。

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:

有四种作用域:

L(Local):最内层,包含局部变量,比如一个函数/方法内部。

E(Enclosing):包含了非局部(non-local)也非全局(non-global)的变量。比如两个嵌套函数,一个函数(或类) A 里面又包含了一个函数 B ,那么对于 B 中的名称来说 A 中的作用域就为 nonlocal。

G(Global):当前脚本的最外层,比如当前模块的全局变量。

B(Built-in): 包含了内建的变量/关键字等。,最后被搜索

规则顺序: L –> E –> G –>gt; B。

在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内置中找。

1418490-20180906153626089-1835444372.png

1、内置作用域是通过一个名为 builtin 的标准模块来实现的,但是这个变量名自身并没有放入内置作用域内,所以必须导入这个文件才能够使用它

2、Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问

#只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的

ifTrue:#这里定义一个局部作用域

msg = 'I am from Runoob'

#局部作用域调用这个局部命名空间

print(msg)#全局作用域去调用局部命名空间,但是模块,类和函数是不能在外部去调用局部命名空间的,注意这里的模块相当于包的概念

print(msg)

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

I amfromRunoob

I amfromRunoob

Process finished with exit code 0

1715935-20201126102022412-1371183492.png

3、全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

4、局部变量如何改为全局变量

1、非嵌套的情况下:

使用global进行修改

num = 1

deffun1():#全局变量变为局部变量

globalnum#输出全局变量

print(num)#重新赋值变量

num = 123

print(num)

fun1()print(num)

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py1

123

123Process finished with exit code 0

2、嵌套情况下使用nonlocal

defouter():

num= 10

definner():#全局变量修改为局部变量

nonlocal num #nonlocal关键字声明

num = 100

print(num)

inner()print(num)

outer()

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py100

100Process finished with exit code 0

注意:nonlocal和global不能一起使用

3、Python3 标准库概览

1、操作系统接口

os模块提供了不少与操作系统相关联的函数。

import os

2、日常的文件和目录管理任务

importshutil

shutil.copyfile('data.db', 'archive.db')

shutil.move('/build/executables', 'installdir')

3、文件通配符

glob模块提供了一个函数用于从目录通配符搜索中生成文件列表:

importglobprint(glob.glob('*.py'))

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

['Test.py']

Process finished with exit code 0

4、命令行参数

通用工具脚本经常调用命令行参数

importsysprint(sys.argv)print(sys.api_version)print(sys.float_info)print(sys.maxsize)

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

['C:/app/FlinkUdf/src/main/Python/Practice/Test.py']1013sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)9223372036854775807Process finished with exit code 0

5、错误输出重定向和程序终止

sys 还有 stdin,stdout 和 stderr 属性,即使在 stdout 被重定向时,后者也可以用于显示警告和错误信息。

importsysprint(sys.argv)print(sys.api_version)print(sys.float_info)print(sys.maxsize)print(sys.modules)print(sys.stderr.write('Warning, log file not found starting a new one\n'))

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

['C:/app/FlinkUdf/src/main/Python/Practice/Test.py']1013sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)9223372036854775807{'sys': , 'builtins': , '_frozen_importlib': , '_imp': , '_thread': , '_warnings': , '_weakref': , 'zipimport': , '_frozen_importlib_external': , '_io': , 'marshal': , 'nt': , 'winreg': , 'encodings': , 'codecs': , '_codecs': , 'encodings.aliases': , 'encodings.utf_8': , '_signal': , '__main__': , 'encodings.latin_1': , 'io': , 'abc': , '_abc': , 'site': , 'os': , 'stat': , '_stat': , '_collections_abc': , 'ntpath': , 'genericpath': , 'os.path': , '_sitebuiltins': , '_bootlocale': , '_locale': , 'encodings.gbk': , '_codecs_cn': , '_multibytecodec': , 'sitecustomize': }47Warning, log filenotfound starting a new one

Process finished with exit code 0

大多脚本的定向终止都使用 "sys.exit()"。

6、字符串正则匹配

re模块为高级字符串处理提供了正则表达式工具。对于复杂的匹配和处理,正则表达式提供了简洁、优化的解决方案:

importreprint(re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest'))print(re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat'))print('tea for too'.replace('too', 'two'))

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

['foot', 'fell', 'fastest']

catinthe hat

teafortwo

Process finished with exit code 0

7、数学

math模块为浮点运算提供了对底层C函数库的访问:

random提供了生成随机数的工具。

importmathimportrandomprint(math.acosh(10))print(math.e)print(random.choice(['apple', 'pear', 'banana']))print(random.sample(range(100), 10))print(random.random())print(random.randrange(6))

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py2.993222846126381

2.718281828459045pear

[37, 66, 81, 75, 95, 24, 13, 16, 25, 9]0.3879468875255455

4Process finished with exit code 0

注意:随机生成一个浮点数random.random(),随机生成一个整数random.randrange(6)

8、日期和时间

datetime模块为日期和时间处理同时提供了简单和复杂的方法。

支持日期和时间算法的同时,实现的重点放在更有效的处理和格式化输出。

该模块还支持时区处理:

importdatetimefrom datetime importdateprint(date.today())print(datetime.date(2003, 12, 2))print((date.today()-datetime.date(2003, 12, 2)).days)

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py2020-11-26

2003-12-02

6204Process finished with exit code 0

9、数据压缩

以下模块直接支持通用的数据打包和压缩格式:zlib,gzip,bz2,zipfile,以及 tarfile。

importzlib

s= b'witch which has which witches wrist watch'

print('压缩前大小:', len(s))print('压缩后大小:', len(zlib.compress(s)))print('解压后内容是:', zlib.decompress(zlib.compress(s)))print('解压后大小:', len(zlib.decompress(zlib.compress(s))))print(zlib.crc32(s))

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

压缩前大小:41压缩后大小:37解压后内容是: b'witch which has which witches wrist watch'解压后大小:41

226805979Process finished with exit code 0

10、性能度量

有些用户对了解解决同一问题的不同方法之间的性能差异很感兴趣。Python 提供了一个度量工具,为这些问题提供了直接答案。

例如,使用元组封装和拆封来交换元素看起来要比使用传统的方法要诱人的多,timeit 证明了现代的方法更快一些。

from timeit importTimerprint(Timer('t=a; a=b; b=t', 'a=1; b=2').timeit())print(Timer('a,b = b,a', 'a=1; b=2').timeit())

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py0.0666407790000001

0.06026570400000009Process finished with exit code 0

相对于 timeit 的细粒度,:mod:profile 和 pstats 模块提供了针对更大代码块的时间度量工具。

11、测试模块

开发高质量软件的方法之一是为每一个函数开发测试代码,并且在开发过程中经常进行测试

doctest模块提供了一个工具,扫描模块并根据程序中内嵌的文档字符串执行测试。

测试构造如同简单的将它的输出结果剪切并粘贴到文档字符串中。

通过用户提供的例子,它强化了文档,允许 doctest 模块确认代码的结果是否与文档一致:

importdoctestdefaverage(values):"""Computes the arithmetic mean of a list of numbers.

>>> print(average([20, 30, 70]))

40.0"""

return sum(values) /len(values)

doctest.testmod()#自动验证嵌入测试

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

Process finished with exit code 0

unittest模块不像 doctest模块那么容易使用,不过它可以在一个独立的文件里提供一个更全面的测试集:

importdoctestdefaverage(values):"""Computes the arithmetic mean of a list of numbers.

>>> print(average([20, 30, 70]))

40.0"""

return sum(values) /len(values)

doctest.testmod()#自动验证嵌入测试

importunittestclassTestStatisticalFunctions(unittest.TestCase):deftest_average(self):

self.assertEqual(average([20, 30, 70]), 40.0)

self.assertEqual(round(average([1, 5, 7]), 1), 4.3)

self.assertRaises(ZeroDivisionError, average, [])

self.assertRaises(TypeError, average,20, 30, 70)

unittest.main()#Calling from the command line invokes all tests

结果:

C:\Anaconda3\envs\FlinkUdf\python.exe C:/app/FlinkUdf/src/main/Python/Practice/Test.py

.----------------------------------------------------------------------Ran1 test in0.001s

OK

Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值