1 属性和方法
●属性
----类属性,直接在类中定义的属性是类属性
----类属性可以通过类或类的实例访问到。但是类属性只能通过类对象来修改,无法通过实例对象修改
----实例属性 通过实例对象添加的属性属于实例属性
----实例属性只能通过实例对象来访问和修改,类对象无法访问修改
●方法
----在类中定义,以self为第一个参数的方法都是实例方法
----实例方法在调用时 Python会将调用对象以self传入
----实例方法可以通过类实例和类去调用
----当通过实例调用时,会自动将当前调用对象作为self传入
----当通过类调用时,不会自动传递self,我们必须手动传递self
----类方法 在类的内容以@classmethod来修饰的方法属性类方法
----类方法第一个参数是cls也会自动被传递。cls就是当前的类对象
----类方法和实例方法的区别,实例方法的第一 个参数是self, 类方法的第一个参数是cls
----类方法可以通过类去调用,也可以通过实例调用
●静态方法
----在类中用@staticmethod来修饰的方法属于静态方法
----静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用
----静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类
中的函数
----静态方法一般都是些工具方法,和当前类无关
类属性和实例属性
咱们先说说类属性和实例属性
class A(object):
# 类属性 直接在类中定义的属性 (其实就是在类中创建了一个变量这么理解也可以)
# 类属性可以通过可以通过类和该类的实例来访问
count=0
a=A()
print(A.count) #通过类来访问类属性
print(a.count) #通过实例来访问类属性
0
0
class A(object):
# 类属性 直接在类中定义的属性 (其实就是在类中创建了一个变量这么理解也可以)
# 类属性可以通过可以通过类和该类的实例来访问
# 类中的属性只能通过类对象来修改,无法通过实例对象来修改
count=0
a=A()
a.count=10
print(A.count)
print(a.count) #我们发现类中的属性没有改变 实例对象中的属性改变了
0
10 # 类中的属性无法通过实例对象来修改
class A(object):
count=0
a=A()
A.count=20
print(A.count)
print(a.count) #我们发现类中的属性改变了 实例对象中的属性也改变了
#如果实例找属性 如 count 会先在自己里 找 没有再去类对象中去找
20
20
那么我们定义的__init__函数中的属性是类属性吗
class A(object):
# 类属性 直接在类中定义的属性 (其实就是在类中创建了一个变量这么理解也可以)
# 类属性可以通过可以通过类和该类的实例来访问
# 类中的属性只能通过类对象来修改,无法通过实例对象来修改
count=0
def __init__(self):
self.name='葫芦娃'
a=A()
#实例属性 通过实例对象来添加的属性就是实例属性
#a.count=10
# A.count=20
print(A.name)
AttributeError: type object 'A' has no attribute 'name'
属性错误:类型对象“A”没有属性“name”
class A(object):
# 类属性 直接在类中定义的属性 (其实就是在类中创建了一个变量这么理解也可以)
# 类属性可以通过可以通过类和该类的实例来访问
# 类中的属性只能通过类对象来修改,无法通过实例对象来修改
count=0
def __init__(self): #(这里特殊的实例属性)
self.name='葫芦娃' 他在类里是确确实实的 但是它却是个实例属性 就是这个葫芦娃是实例属性 因为self 表示 当前对象添加的属性 其实他是添加到当前对象(实例对象)中了
a=A()
#实例属性 通过实例对象来添加的属性就是实例属性
#a.count=10
# A.count=20
print(a.name)
葫芦娃
方法
实例方法
●方法
实例方法
----在类中定义,以self为第一个参数的方法都是实例方法
----实例方法在调用时 Python会将调用对象以self传入
----实例方法可以通过类实例和类去调用
----当通过实例调用时,会自动将当前调用对象作为self传入
----当通过类调用时,不会自动传递self,我们必须手动传递self (此处指的是实例 如a 若是直接传递self self 这个name没有被定义)
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#
def text(self): #这个self并不需要传递 谁调用就是谁
print('这是test方法')
a=A()
这是test方法
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#
def text(self): #这个self
print('这是test方法',self)
a=A()
a.text()
这是test方法 <__main__.A object at 0x00000000020B3520>
试试A.text( )行不行
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法')
a=A()
A.text()
TypeError: text() missing 1 required positional argument: 'self'
类型错误:text()缺少1个必需的位置参数:“self”
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法')
a=A()
A.text(a) 由此可以看出 a.text() 等价于 A.text(a)
这是test方法
类方法
----类方法 在类的内容以@classmethod来修饰的方法属性类方法
----类方法第一个参数是cls也会自动被传递。cls就是当前的类对象
----类方法和实例方法的区别,实例方法的第一 个参数是self, 类方法的第一个参数是cls
----类方法可以通过类去调用,也可以通过实例调用 (就是上述的用类调用实例方法是得加上 self (a) 而用实例调用类方法是什么都不用加的)
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法',self)
#类方法
#在类的内部使用 @classmethod 来修饰的方法属于类方法
#类方法的第一参数我们习惯写成cls 也会自动传递 clas就相当于当前的类对象
@classmethod
def test2(cls):
print('这个是test2方法',cls)
a=A() #a.text() 等价于 A.text(a)
A.test2()
这个是test2方法 <class '__main__.A'>
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法',self)
#类方法
#在类的内部使用 @classmethod 来修饰的方法属于类方法
#类方法的第一参数我们习惯写成cls 也会自动传递 clas就相当于当前的类对象
@classmethod
def test2(cls):
print('这个是test2方法',cls)
print(cls.count) #也可以用cls 访问类属性
a=A() #a.text() 等价于 A.text(a)
A.test2()
这个是test2方法 <class '__main__.A'>
0
类方法可以通过类去调用,也可以通过实例调用 (就是上述的用类调用实例方法是得加上 self (a) 而用实例调用类方法是什么都不用加的)
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法',self)
#类方法
#在类的内部使用 @classmethod 来修饰的方法属于类方法
#类方法的第一参数我们习惯写成cls 也会自动传递 clas就相当于当前的类对象
@classmethod
def test2(cls):
print('这个是test2方法',cls)
print(cls.count)
a=A() #a.text() 等价于 A.text(a)
a.test2()
这个是test2方法 <class '__main__.A'>
0
静态方法
●静态方法
----在类中用@staticmethod来修饰的方法属于静态方法
----静态方法不需要指定任何的默认参数,静态方法可以通过类和实例调用
----静态方法,基本上是一个和当前类无关的方法,它只是一个保存到当前类
中的函数
----静态方法一般都是些工具方法,和当前类无关
咱们再试一下静态方法
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法',self)
#类方法
#在类的内部使用 @classmethod 来修饰的方法属于类方法
#类方法的第一参数我们习惯写成cls 也会自动传递 clas就相当于当前的类对象
@classmethod
def test2(cls):
print('这个是test2方法',cls)
print(cls.count)
#静态
#在类中使用 @staticmethod来修饰的方法我们称之为静态方法
#不需要制定任何的默认参数 静态方法可以被类对象和实例对象调用
#静态方法跟类本身无关 就是一个功能函数
@staticmethod
def test3():
print('这是test3方法')
a=A() #a.text() 等价于 A.text(a)
A.test3()
这是test3方法
class A(object):
count=0
def __init__(self):
self.name='葫芦娃'
#实例方法
#在类中定义 以self为第一个参数的方法都是实例方法
#当通过实例对象调用时 会自动传递当前对象作为self传入
#当通过类去调用时 不会自动传递self
def text(self): #这个self
print('这是test方法',self)
#类方法
#在类的内部使用 @classmethod 来修饰的方法属于类方法
#类方法的第一参数我们习惯写成cls 也会自动传递 clas就相当于当前的类对象
@classmethod
def test2(cls):
print('这个是test2方法',cls)
print(cls.count)
#静态
#在类中使用 @staticmethod来修饰的方法我们称之为静态方法
#不需要制定任何的默认参数 静态方法可以被类对象和实例对象调用
#静态方法跟类本身无关 就是一个功能函数
@staticmethod
def test3():
print('这是test3方法')
a=A() #a.text() 等价于 A.text(a)
A.test3()
这是test3方法
就比如 我这里有个函数 放在全局里不好 放在哪都不好 这时候你希望有个地方去存的的时候 就可以给他整成一个静态方法
2 模块
–模块的简介–
模块化
●模块化指将一个完整的程序分解成一个个的小模块
●通过将模块组合,来搭建出一个完整的程序
●模块化的优点
----方便开发
----方便维护
----模块可以复用
3模块的创建
●在Python当中一个py文件就是一个模块
●在一个模块中引入外部模块 import 模块名(模块名就是py文件)
●可以引入同一个模块多次,但是模块的实例只会创建一次
●import 模块名 as 模块别名
●在一个模块内部都有一个__name__。通过它我们可以获取模块的名字
●如果py文件直接运行时,那么__name__默认等于字符串’main’。
__name__属性值为__main__的模块是主模块。一个程序中只有一个主模块
运行一下模块文件 结果是这是我的第一个模块
接着上面的操作
#在python 中一个py文件就是一个模块
#在一个模块中引入外部模块
#1 import 模块名(模块名就是python的文件名)
import test_m
import test_m
import test_m #运行后
这是我的第一个模块
#在python 中一个py文件就是一个模块
#在一个模块中引入外部模块
#import 模块名(模块名就是python的文件名)
#可以引入同一个模块多次 但是模块只会执行一次
import test_m
print(test_m)
这是我的第一个模块
<module 'test_m' from 'D:\\LongProject\\test_m.py'>
module就是模块 模块tset_m 从D盘 LongProject夹 的test_m.py 这来的 (这就是一个模块名字指向的路径)
接下来说一个非常非常重要的东西
我们先在test_m.py 中 来个print(name)
我们再在 模块.py 中引入模块 test_m
运行一下后 应该是打印__name__
然而
name
模块就是test.py 模块.py 这些文件
在每一个模块中都有__name__ 我们可以用它来获取模块的名字
上面说的__name__ 我们可以用它来获取模块的名字
但是这里却是__main__
如果这个模块直接运行 那么__name__ 默认的字符串 main 表示当前文件为主文件
#如果这个模块直接运行 那么__name__ 默认的字符串 __main__ 表示当前文件为主文件
print(__name__)
__main__
4 模块的使用
●访问模块中的变量 语法是 模块名.变量名
●访问模块中的函数 语法是 模块名.函数名
●访问模块中的对象 语法是 模块名.对象名
●我们也可以引入模块中部分内容 语法 from 模块名 import 变量,变量…(第三种引入模块方法)
●还有一种引入方式 语法 from 模块名 import 变量 as 别名 (第二种)
第一种引入模块的方式
访问模块中的变量
访问模块中的函数
上图上面还有 一个import test_m
import test_m
#访问模块中的函数 语法是 模块名.函数名
test_m.test1() #比较像 import requests
# requests.get() 这个形式
test_m.test2()
test1
test2
●访问模块中的对象 语法是 模块名.对象名
类也是对象
在模块中定义类
再把print(p.name) 注释掉
第二种引入模块的方式
第二种引入模块方法 2 import 模块名 as 模块别名
模块.py 中
#2 import 模块名 as 模块别名
import test_m as test
print(test_m)
NameError: name 'test_m' is not defined
#2 import 模块名 as 模块别名
import test_m as test
print(test)
这是我的第一个模块
<module 'test_m' from 'D:\\LongProject\\test_m.py'>
第三种引入模块的方式
第三种引入模块方法
#第3种语法 from 模块名 import 变量
test_m 测试模块中
由上我们可以看出 以第三种方式是无法打印出test_m 这个对象的
在test_m 测试模块中的前提上
#第3种语法 from 模块名 import 变量,变量,变量
#3 语法 from 模块名 import 变量,变量,变量
第四种引入模块的方式
#第4种 语法: from 模块名 import *
依然是在模块test_m (测试模块)基础上
当然第四种方法没有第一种保险
比如我们在主模块 中
def test1():
print('主模块中的test1')
由上图可看出 test1()调用的是 测试模块的 test()函数 而非 主模块的
由上可得出在引入模块后再定义函数 你再 调用函数那都是主模块的函数(灰色)
引入模块是灰色的 那他就没被引入
方法一与方法二的区别
就算主模块也定义有函数test1() (当然前提是不在引入模块后定义的)第三种方式还是会去调用测试模块的函数 而 第一种与之相反
第五种引入模块的方式
#5 语法:from 模块名 import 变量 as 别名
就是你的主模块和你的测试模块出现相同名称的函数的时候
那么我们可以给他起一个别名
意思就是给测试模块 test_m 中的 test1()函数起了新名字 new_test1
在测试模块 test_m 中 加入私有变量c=3
咱们之前学封装可以_c=3
##我们再尝试一个
在测试模块中
在主模块中运行.
然后你就发现了测试模块中的测试代码也打印 了
我们写的测试代码是为了测试模块没什么问题 而在主模块一引用 测试代码在主模块又执行了
所以我们希望编写测试 或者我们编写一部分代码 只在当前文件为主文件时可以执行 而其他模块 在引入这个模块时 就不要在执行了 (此问题前面也出现过 但未强调)
所以我们可以做一个判断来解决此问题
#
# #在模块中定义变量
a=1
b=2
#c是私有的(不希望你去修改)
_c=3
#
#
# # 在模块中定义函数
def test1():
print('test1')
def test2():
print('test2')
# # 在模块中定义类
class Person():
def __init__(self):
self.name='葫芦娃'
p=Person()
if __name__ =='__main__':
#以下是测试代码
print(p.name)
test1()
test2()
所以主模块中就不再发生类似的尴尬
迭代器和生成器
迭代器
#迭代器 访问元素的一种方式 (遍历也是一种访问元素的一种方式)
#特点是可以记住遍历位置的对象
#迭代器也是从序列当中第一个元素访问 直到所有的元素被访问完结束(而且迭代器是只会往前不会后退)
#iter() next() (其实整个迭代器都是围绕这两个方法的)
#迭代器 访问元素的一种方式 (遍历也是一种访问元素的一种方式)
#特点是可以记住遍历位置的对象
#迭代器也是从序列当中第一个元素访问 直到所有的元素被访问完结束(而且迭代器是只会往前不会后退)
#iter() next() (其实整个迭代器都是围绕这两个方法的)
lst=[1,2,3,4,5,6,7]
myiter=iter(lst)
print(next(myiter))
1
lst=[1,2,3,4,5,6,7]
myiter=iter(lst)
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
1
2
3
4
5
6
7 你在来个print(next(myiter)) 就会报错 StopIteration
停止迭代
但是这样写太多重复代码了
我们经常用的方法是
lst=[1,2,3,4,5,6,7]
myiter=iter(lst)
for i in myiter: # 迭代数据结构
print(i)
1
2
3
4
5
6
7
生成器
#生成器 在Python 中使用yield 这个关键字 我们就称之为生成器或者生成器函数
#生成器和普通函数的区别 返回的是一个迭代器的函数 只用于迭代器作业 (可以简单的理解生成器就是一个特殊的迭代器)
#next() 方法 当前位置继续访问
def fn():
print('11')
yield 1
print('12')
yield 2
print('13')
yield 3
print('14')
yield 4
print('15')
yield 5
print(type(fn)) #<class 'function'>
f=fn()
print(type(f))
<class 'function'>
<class 'generator'> generator就是生成器的意思
def fn():
print('11')
yield 1
print('12')
yield 2
print('13')
yield 3
print('14')
yield 4
print('15')
yield 5
# print(type(fn)) #<class 'function'>
f=fn()
# print(type(f))#<class 'generator'>
next(f)
11
def fn():
print('11')
yield 1
print('12')
yield 2
print('13')
yield 3
print('14')
yield 4
print('15')
yield 5
# print(type(fn)) #<class 'function'>
f=fn()
# print(type(f))#<class 'generator'>
# next(f)# 11
print('返回:',next(f))
11 可以看出先是打印11 再返回
返回: 1
def fn():
print('11')
yield 1
print('12')
yield 2
print('13')
yield 3
print('14')
yield 4
print('15')
yield 5
# print(type(fn)) #<class 'function'>
f=fn()
# print(type(f))#<class 'generator'>
# next(f)# 11
print('返回:',next(f))# 11 返回:1
print('返回:',next(f))# 12 返回:2
print('返回:',next(f))# 13 返回:3
11
返回: 1
12
返回: 2
13
返回: 3
yied 也是在返回值 但是它跟return 不太一样 return 是返回后下面的代码都不会在执行
(这算是一个拓展的内容)