Python(七)

类属性(可以理解为类中共享的全局变量)

实例属性

  • 所属于具体的实例对象,不同实例对象之间的实例属性互不影响

类属性

  • 所属于类对象,多个实例对象之间共享同一个类属性
  • 获取类属性方法:类名.类属性
  • 通过实例对象不能够修改类属性

实例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Person:
#类属性
sum_num = 0
def __init__(self,name):
#赋值给实例属性
self.name = name
#修改类属性值,每创建一个实例对象,类属性值+1
Person.sum_num += 1

p1 = Person('zhangsan')
#通过实例对象访问类属性,通过类名访问类属性
print(p1.sum_num,Person.sum_num)

p2 = Person('lisi')
print(p1.sum_num,p2.sum_num,Person.sum_num)

##为什么没有构造实例对象的实例属性sum_num,还可以获取值?如果没有实例属性就会去类属性。

结果:

1
2
1 1
2 2 2

实例2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person:
#类属性
sum_num = 0
def __init__(self,name):
#赋值给实例属性
self.name = name
#修改类属性值,每创建一个实例对象,类属性值+1
#Person.sum_num += 1

p1 = Person('zhangsan')
#通过实例对象访问类属性,通过类名访问类属性
#print(p1.sum_num,Person.sum_num)

p2 = Person('lisi')

##通过实例对象p1,来修改类属性的值
p1.sum_num = 100
print(p1.sum_num,p2.sum_num,Person.sum_num)

结果:

1
2
3
100 0 0

#由结果可知,通过实例对象不能修改类属性的值,如果修改的属性在实例中不存在,则动态添加实例属性

实例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Person:
#类属性
sum_num = 0
def __init__(self,new_name,new_num):
#赋值给实例属性
self.name = new_name
#定义一个与类属性同名的实例属性
self.sum_num = new_num
#修改类属性值,每创建一个实例对象,类属性值加1
Person.sum_num += 1

p1 = Person('zhangsan',10)
print(p1.sum_num,Person.sum_num)

结果:

1
2
3
10 1

#由结果可以看出,同时调用同名属性的时候,优先调用对象属性,不是类属性

类方法、静态方法

类方法—操作类属性

  • 所属于类对象,使用@classmethod修饰的方法
  • 定义类方法的第一个参数通常以”cls”参数作为类对象被传入
  • 调用方式:类名.类方法 或者 实例对象.类方法(不推荐)

实例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Person:
#类属性
sum_num = 0
def __init__(self,new_name):
#赋值给实例属性
self.name = new_name

#类方法
@classmethod
def add_sum_num(cls): #cls表示类对象
cls.sum_num += 1
print(cls.sum_num)


#类方法调用
#方法1 :类名.类方法
Person.add_sum_num()
print('============分割线============')
#:方法2:实例对象.类方法(不推荐这样调用类方法)
p = Person('zhangsan')
p.add_sum_num()

#类方法(cls)和实例方法(self),类方法--类属性,实例方法--实例属性(很重要!!!)

结果:

1
2
3
1
============分割线============
2

静态方法—-和类和对象没有太大关系

  • 使用@staticmethod修饰的方法,不需要默认传递任何参数
  • 调用方式:类名.静态方法 或者实例对象.静态方法

实例4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Person:
#类属性
sum_num = 0
def __init__(self,new_name):
#赋值给实例属性
self.name = new_name

#类方法
@classmethod
def add_sum_num(cls): #cls表示类对象
cls.sum_num += 1
print(cls.sum_num)

#静态方法,静态方法里面不用传入参数的
@staticmethod
def static_test():
print('----静态方法----')
Person.sum_num += 1
print(Person.sum_num)

#调用静态方法(尽量少使用静态方法,如果要使用的话,可以在打印提示性的信息时候使用)
Person.static_test()
print('------------')
p = Person('zhangsan')
p.static_test()

#总结:在类方法和静态方法中不能直接调用实例属性

结果:

1
2
3
4
5
----静态方法----
1
------------
----静态方法----
2

单例类

new(cls)

  • 超类object类内置的方法,用户创建对象,返回创建对象的引用
  • 必须要提供cls参数,代表类对象
  • 必须要有返回值,返回创建对象的引用

实例5:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"""
#过程:解释器先用new方法来创建object对象,然后返回一个引用来给init构造方法,
self就相当于返回对象的一个引用,接收到这个对象后,对对象进行初始化,
打印构造方法后,返回对象的引用给变量db,变量db就指向内存中创建的这个对象。


# cls-->类对象 self-->是传入的对象本身

"""

class DataBaseObj(object): #object是可以省略的,缺省object #init方法是无返回值
def __init__(self,new_name): #对象的初始化
print('-----init构造方法------')
self.name = new_name
print(self.name)

def __new__(cls,name): #object类是所有类的基类,object这个类的new方法是创建对象
print('cls_id:',id(cls))
return object.__new__(cls)


print(id(DataBaseObj)) ##打印的类对象的id
db = DataBaseObj('mysql')
print('----分割线-----')
print(db)

结果:

1
2
3
4
5
6
1706654249752
cls_id: 1706654249752
-----init构造方法------
mysql
----分割线-----
<__main__.DataBaseObj object at 0x0000018D5ED1FE10>

单例类

  • 在整个程序系统中确保某一个类只有一个实例对象

实例6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#单例类
class SingleInstance:
__instance = None
def __init__(self):
print("-----init-----")
def __new__(cls):
if cls.__instance == None:
cls.__instance = object.__new__(cls)
return cls.__instance

s1 = SingleInstance()
print(id(s1))
s2 = SingleInstance()
print(id(s2))

结果:

1
2
3
4
-------init-------
1706683752288
-------init-------
1706683752288

异常处理

链接:异常处理

捕获异常

1
2
3
4
try:
逻辑代码块
expect ExceptionType as err:
异常处理方法

实例7:

1
2
3
4
5
6
7
try:
open("test.txt", "r")

except FileNotFoundError as err:
print('捕获到了异常!文件不存在',err)

print('哈哈哈哈')

结果:

1
2
捕获到了异常!文件不存在 [Errno 2] No such file or directory: 'test.txt'
哈哈哈哈

捕获多个异常

1
2
3
4
try:
逻辑代码块
except (ExceptionTypl1, ExceptionType2, ···) as err:
异常处理方法

实例8:

1
2
3
4
5
6
7
8
try:
print(num)
print("==============")
open("test.txt", "r")
except (NameError,FileNotFoundError) as err: #用元组将所有异常括起来
print("捕获到了异常!",err)

print("哈哈哈哈哈")

结果:

1
2
捕获到了异常! name 'num' is not defined
哈哈哈哈哈

捕获所有可能发生的异常

1
2
3
4
5
6
try:
逻辑代码块
except (ExceptionType1, ExceptionType2, ···) as err:
异常处理方法
except ExceptionType as err:
异常处理方法

实例9:

1
2
3
4
5
6
7
8
try:
open("test.txt", "r")
except NameError as err1:
print("捕获到了异常!",err1)
except Exception as err2:
print("捕获所有可能的异常",err2)

print("哈哈哈哈哈")

结果:

1
2
捕获所有可能的异常 [Errno 2] No such file or directory: 'test.txt'
哈哈哈哈哈

finally

1
2
3
4
5
6
7
8
try:
逻辑代码块
exception(ExceptionType1, ExceptionType2, ···) as err:
异常处理方法
except ExceptionType as err:
异常处理方法
finally:
无论是否有异常产生,都会执行这里的代码块

实例10:

1
2
3
4
5
6
7
8
9
10
11
f = None
try:
f = open("test.txt","r")
print("打印文件内容")
except FileNotFoundError as error:
print("捕获到了异常",error)
finally:
print("关闭文件")
if f != None:
print("正在关闭文件")
f.close()

结果:

1
2
捕获到了异常 [Errno 2] No such file or directory: 'test.txt'
关闭文件

函数嵌套异常传递

实例11:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def test1(): #通过打印的方式也可以查询问的所在处
print("------test1-1--------")
print(num) #打印一个不存在的变量
print("------test1-2--------")

def test2():
try:
print("------test2-1--------")
test1()
print("------test2-2--------")
except Exception as error:
print("捕获到异常",error)

print("------test2-3--------")

test2()

结果:

1
2
3
4
5
6
7
8
9
------test2-1--------
------test1-1--------
捕获到异常 name 'num' is not defined
------test2-3--------


##总结:异常处理的意义是防止某个业务产生异常而影响到整个程序中的其他业务。

##当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

包和模块(包可以类比成文件夹)

链接:模块和包

模块的名字: .py文件的名字

下面是关于pycharm,能够引用包的设置步骤:若设置成功,则文件夹中间是实心,而非空心。

下图是包的形式,以.py的文件名字,包分别是bussiness和tool:

包下可以包含子包

不同包下可以有相同的模块名称,使用‘包名.模块名’的方式区分

实例12:

1
2
3
4
5
import bussiness.model1,tool.model1
#import tool.model1

bussiness.model1.project_info()
tool.model1.tool_info()

引入模块的方式

  • 引入单个模块:import module_name
  • 引入多个模块:import module_name1,module_name2,···
  • 引入模块中的指定函数:from module_name import func1,func2,···

实例13:

1
2
3
4
5
from bussiness import * #批量导入
model3.test1()
model3.test2()
model3.test3()
model1.project_info()

包中必须包含一个默认的init文件

  • 用于标识一个包,而不是普通的文件夹
  • 会在包或者该包下的模块被引入时自动调用
  • 常用于设置包和模块的一些初始化操作

实例14:

1
2
3
4
5
#init可以对包进行初始化的设置
print("init文件被自动调用")

#__all__方法,这里指只有model3才能被其他的引用
__all__ = ["model3"]

-------------本文结束感谢您的阅读-------------


本文标题:Python(七)

文章作者:HuXuzhe

发布时间:2018年07月08日 - 14:07

最后更新:2018年11月21日 - 15:11

原始链接:https://huxuzhe.github.io/2018/07/08/Python-七/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

HuXuzhe wechat
关注微信公众号:"AI数据分析算法",轻轻扫一扫,加入我们的AI_LEGENDS !
坚持原创,您的支持将鼓励我继续创作!
0%