Python随记【二】

选择与循环


字符串


字符串格式化解析

.format()使用详解

字符串方法

字符串常用方法

字符串常用操作方法

.format()函数使用中,{}中的格式控制标记顺序分别为:填充—>对齐—>宽度—>,—>.精度—>类型

1
2
3
4
5
6
#创建映射表,将字符"abcdef123"一一对应地转换为"uvwxyz@#$"
>>> table = ''.maketrans('abcdef123', 'uvwxyz@#$')
>>> s = "Python is a greate programming language. I like it!"
#按映射表进行替换
>>> s.translate(table)
'Python is u gryuty progrumming lunguugy. I liky it!'

正则表达式


正则表达式使用某种预定义的模式去匹配一类具有共同特 征的字符串,主要用于处理字符串,可以快速、准确地完 成复杂的查找、替换等处理要求,在文本编辑与处理、网 页爬虫之类的场合中有重要应用。

函数的设计和使用


首先了解到Python变量名和它的值是一个类似字典的键值对关系,不同的命名空间可以看作不同的字典,我们在使用变量的时候调用规则是LEGB规则,查找使用一个变量,顺序为L-E-G-B,可以理解顺序查找这几个字典中有没有我们使用的变量名,有则调出使用该变量名映射的值,没有则按照顺序向上一级寻找,除非声明global或者noglobal,这样我们就将这个变量声明到了global或者noglobal字典中,同时调用

Python面向对象程序设计


<一>基础概念

  • 类(Class)是用来描述具有相同属性(Attribute)方法(Method)对象的集合。
  • 属性(Attribute): 类里面用于描述所有对象共同特征的变量或数据。比如学生的名字和分数。
  • 方法(Method): 类里面的函数,用来区别类外面的函数, 用来实现某些功能。比如打印出学生的名字和分数。

创建类时用变量形式表示的对象属性称为数据成员用函数形式表示 的对象行为称为成员方法,成员属性和成员方法统称为类的成员。

属性是指一种从现实中抽象出来的某种事物的属性,但是实现在变量和函数上

<二>python面向对象语法中的特别点

1、pass关键字

Python提供了一个关键字“pass”,类似于空语句,可以 用在类和函数的定义中或者选择结构中。当暂时没有确定 如何实现功能,或者为以后的软件升级预留空间,或者其 他类型功能时,可以使用该关键字来“占位”。

因为python中没有大括号来区别各种结构,所有我们只能使用pass来代表空结构

2、构造函数

构造函数名称均为__init__

3、 self参数和cls参数

  • self表示一个具体的实例本身
  • cls表示这个类本身

类的所有实例方法都必须至少有一个名为self的参数,并且必须是方法的第一个形参(如果有多个形参的话), self参数代表将来要创建的对象本身。

在外部通过对象调用对象方法时并不需要传递这个参数, 如果在外部通过类调用对象方法则需要显式为self参数传值。

1
2
3
4
例如
test1=Test()
test1.testP()
Test.testP(test1)

4、类变量和实例变量的定义

  • 类变量:定义在类中且在函数体之外。类变量在所有的实例变量中是共享的类似于静态变量
  • 实例变量:定义在实例方法中的变量。一般的实例变量我们设置在构造函数里,当然也可以在其他函数体中创建

实例变量的定义必须为sefl.变量名=,若直接使用变量名=则为函数内的局部变量,在类方法中定义的cls.变量名=是类变量

访问实例变量也需要self.变量名

5、实例方法和类方法和静态方法

  • 实例方法:只能通过实例对象调用,因为实例方法第一个定义的参数必须是实例对象本身self
  • 类方法:定义类方法,要使用装饰器@classmethod,定义的第一个参数一般是cls,代表这个类本身
  • 静态方法:定义静态方法使用装饰器@staticmethod,没有默认的必须参数,可以通过类和实例直接调用。
  • self和cls是我们的默认名称比较统一,也可以使用其他名称,但是在python语言的特性下,是不过是我们表面上换了个名字而已

类方法和静态方法区别:类方法自带参数cls代表本身类,而静态方法不带参数。所以在函数体中使用类的变量的区别就是类方法可以以cls调用这个类的属性,而静态方法需要以类名去调用,相当于是一个类外函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class A(object):
a = 'a'
@staticmethod
def foo1(name):
print ('hello', name)
print (A.a) # 正常
print (A().foo2('mamq'))
def foo2(self, name):
print ('hello', name)

@classmethod
def foo3(cls, name):
print ('hello', name)
print (A.a)
print (cls().foo2(name))

A.foo1("lyxf")
A.foo3("lyxf")
输出结果相同

由于python的特性其中中没有public、static 这样的修饰符,所以我们才用了@classmethod修饰器来表示

参考文章:

python中的cls到底指的是什么,与self有什么区别?

6、可动态为自定义类和对象增加或者删除成员

动态添加对象属性

针对对象动态添加的属性,是绑定在该对象身上的,在同类其他对象上是没有的的。

动态添加类属性

针对类动态添加的属性,可以增添到使用到所有的该类创建的对象上

由于动态语言的特性,哪怕你是后添加的类属性,之前创建的对象也会增加新的类属性

动态添加对象行为

如果直接添加,调用的时候需要将本身的对象作为参数传入

1
2
3
4
5
6
7
8
class Demo:
pass
t = Demo()
def test(self,a):
print(a)
t.test=test
t.test(t,3)
#结果为输出3

而特殊的

1
2
3
4
5
6
7
8
class Demo:
pass
t = Demo()
def test(a):
print(a)
t.test=test
t.test(3)
#结果为输出3

虽然可执行,但是是因为我们没有使用self,如果增加一个函数中定义实例变量就必须使用self,而且这样也不符合类中的定义方法的习惯所以一般不要使用

而我们想不传入对象参数,可以使用types模块的MethodTpye功能

1
2
3
4
5
6
7
8
9
10
import  types
class Demo:
pass
t = Demo()
def test(self,a):
self.value=a
print(self.value)
t.test=types.MethodType(test,t)
t.test(3)
#结果为输出3

因为在Python中,函数和方法是有区别的。方法一般指与特定 实例绑定的函数,通过对象调用方法时,对象本身将被作为第一个参数隐式传递过去,普通函数并不具备这个特点。如果我们只是使用‘=’,根据python的特点,我们使用的依旧是函数,但是我们通过MethodTpye功能可以生成一个绑定了对象的方法,这样才真正动态为对象添加了一个方法

动态添加类行为

同理我们为类动态添加行为

1
2
3
4
5
6
7
8
9
10
11
import  types
class Demo:
pass
t = Demo()
def test(cls,a):
cls.value=a
print(cls.value)
Demo.test=types.MethodType(test,Demo)
Demo.test(3)
t.test(3)
#输出为两行3,动态增加了类方法
而使用del 可以动态删除类中或者对象的各种属性
1
2
3
例如:
del Test.d
del Test.func

注意方法只能通过类名+方法名删除,不能通过对象删除,实例变量只能通过对象删除

7、私有成员、保护成员与公有成员

类里面的私有属性私有方法以双下划线__开头。私有属性或方法不能在类的外部被使用或直接访问

类里面的保护属性保护方法以单下划线_开头。不能用于 from module import *

公有成员则不加下划线

这里特别指出两边都加双下划线是一些特殊函数,如构造函数、析构函数等

注意:保护成员可以直接修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test:
__a="类私有"
_b="类保护"
d="类公有"
def __init__(self):
self._c = "实例保护"
def __testPrivate(self):
print(self.d)

t1=Test()
print(t1._c)
print(Test._b)
t1._c="实例保护更改"
print(t1._c)
#输出为
#实例保护
#类保护
#实例保护更改

推荐阅读:

Python中的单下划线和双下划线使用场景

9、Python中不存在严格意义上的私有成员

对象外部可以通过“对象名._类名__xxx”这样 的特殊方式来访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test:
__a="类私有"
_b="类保护"
d="类公有"
def __init__(self):
self._c = "实例保护"
self.__d="实例私有"
t=Test()
print(Test._Test__a)
#这里使用对象名._类名__xxx代表通过t使用类私有变量,若为类名._类名__xxx则代表通过类使用类私有变量
print(t._Test__d)
#输出为
#类私有
#实例私有

可以理解为Python私有保护机制只是识别后给我们内部“改了名”,在前面增加了单下划线+类名,同理可以使用对象名._类名xxx直接调用私有方法

10、property的使用完善封装机制

(1)@property和setter、getter修饰器

建议阅读:

@property

(2)property函数

建议阅读:

property函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Test:
def __init__(self, value):
self.__value = value
def __get(self):
return self.__value
def __set(self, v):
self.__value = v
def __del(self):
del self.__value
value = property(__get, __set,__del)
def show(self):
print(self.__value)
t=Test(5)
t.show()
t.value=10
t.show()
print(t.value)
del t.value
#输出为
#5
#10
#10

修改、读取、删除,需要几种对值的权限操作就在property函数相应顺序(读->写->删)放置对应函数

我们要理解,使用get,set方法,而不是直接赋值,是因为能在方法中进行各种设值的限制,因为python的特性,动态添加和修改可以修改成任意类型任意大小的值,很容易出错,使用方法可以通过控制语句在其中添加限制条件,选择出符合要求的值进行添加。而property的使用使得这个方法能够想变量一样简单使用

<三>常用特殊方法

值得注意的是运算符重载就是通过重写特殊方法实现的

<四>继承和多态机制

1、定义继承类

1
2
3
4
5
6
7
class TestParent:
def __init__(self,name):
self.name=name
class Test(TestParent):
pass
test=Test("parent")
print(test.name)

在定义的类名后加括号依次写入父类,Python支持多继承

2、多态实现

根据继承特性:

  • 私有成员不会被继承
  • 公有成员会被继承,在子类中重写父类的方法,调用子类的对象时会使用重写的方法
  • 若子类无构造函数则继承父类构造函数,若有则使用该构造函数而不使用父类的
  • 如果需要在派生类中调用基类的方法,可以使用内置函数 super()或者通过“基类名.方法名()”的方式来实现这一目的。

3、多继承机制

  • 如果父类中有相同的方法名,而在子类中使用时 没有指定父类名,则Python解释器将从左向右按顺序进行搜索,找到第一个后边不再向后解析
  • 在Python 3.x的多继承树中,如果在中间层某类有向上一 层解析的迹象,则会先把本层右侧的其他类方法解析完, 然后从本层最后一个解析的类方法中直接进入上一层并继 续解析,也就是在从子类到超类的反向树中按广度优先解析

-----------------------本文结束 感谢阅读-----------------------
坚持原创技术分享,您的支持将鼓励我继续创作!恰饭^.^~