一、python
1.python的基础语法
1.python的介绍
概述
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。
Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。
Python 是一种解释型语言: 这意味着开发过程中没有了编译这个环节。类似于PHP和Perl语言。
Python 是交互式语言: 这意味着,你可以在一个Python提示符,直接互动执行写你的程序。
Python 是面向对象语言: 这意味着Python支持面向对象的风格或代码封装在对象的编程技术。
Python 是初学者的语言:Python 对初级程序员而言,是一种伟大的语言,它支持广泛的应用程序开发,从简单的文字处理到 WWW 浏览器再到游戏
2.python的注释方法
1.单行注释:#
单行注释常以#
开头
windows的快捷键是 Ctrl + /
实例:
# -太棒了
print ("hello world!"); #您好,世界
2.多行注释:三个单引号(’’’)或者三个双引号(”””)
注释使用三个单引号(’’’)或者三个双引号(”””)
来标记,而实际上这是多行字符串的书写方式,并不是Python本身提倡的多行注释方法
实例:
'''
这是多行注释,使用单引号。
这是多行注释,使用单引号。
'''
"""
这是多行注释,使用双引号。
这是多行注释,使用双引号。
"""
3.python的数据类型
# int
a = 3
#float
a = 3.3
# str
a = 'str'
# bytes
a = b'4'
# complex
a = 2 + 3j
# bool
a = True
# None
a = None
Python语法比较松散,语句的最后不强制要求加’;’,在定义变量时,不需要声明变量的数据类型,Python会根据变量的赋值自动给定数据类型
如果在定义一个变量时不确定他的类型,可以使用None来进行赋值,此时的类型也是None Type
4.面向对象
面向对象编程是一种封装代码的方法;代码封装就是隐藏实现功能的具体代码,仅留给用户使用的接口。
Python中也支持面向对象的三大特征:封装、继承、多态。
面向对象的相关术语
类:可以理解是一个模板,通过它来创建出无数个具体的实例;类是抽象一类事物的总称,
对象:类时不可以直接使用的,需要通过类创建的实例才能使用,这个实例也就是对象。
属性:类中的所有变量称为属性
方法:类中的所有函数通常叫做方法
这里的重点就是类和对象。
类的命名规则首字母最好大写,可以采用驼峰写法,例如:StudentName
python中的类也是通过用class来定义,并且他也可以下成“class student(object)”的方式来定义,括号内的是class所继承的父类,如果不知道又想写的话写object就行。
2.python的构造函数
1.python中构造函数的格式为:__init__()
想让类定义不同对象,我们需要构造函数。不同的构造函数能赋予不同的属性
#c9_1.cy
class Array1:
'''
类里面的变量我们称做
类变量
'''
data = 'ring01'
size = 1
# def __init__(self):
def __init__(self):
'''
构造函数,基本是通用的,包括php,java都有构造函数
'''
print('Array1')
def get_size(self):
print('get_size')
1.上述中class Array1后面的父类是默认跟object。class Array1(父类):
2.其中python当中的self如同java等其他语言的this,可以进行修改但是不建议这样做。
3.python中类实例化后一瞬间自动执行
实例化后自动执行例如:
from c9_1 import Array1, Array2
arr = Array1()
结果
在运行python后我们发现它自动打出了Array1,但是我们没有进行print的显示语句
2.python查看变量内存地址:id
如果实例化对象是相同的,这里的相同只是内部变量值,方法相同但计算机中但内存地址不同。
from c9_1 import Array1, Array2
arr = Array1()
arr1 = Array1()
arr2 = Array1()
#
print(id(arr), id(arr1), id(arr2))
结果:三个内存地址不同
3.显式调用构造函数,会变成普通函数
from c9_1 import Array1, Array2
arr = Array1()
arr.__init__()
结果:虽然这里显示了,但是这个构造函数已经变成了普通函数。【显示两次,一次实例化显示一次print调用构造函数显示】
为什么打印出了两次
构造函数的特性:
1.构造函数在类实例化的同时,就已经自动运行了
2.构造函数能不能显式调用,明显是可以的 但在编程中不要这样调用
4.构造函数的返回值
from c9_1 import Array1, Array2
arr = Array1()
a = arr.__init__()
print(a)
print(type(a))
结果:
结果中两个 Array1 已经解释过了,但是为什么有None的数据类型
解释:
1.没有return ?
2.构造函数应该返回none而不是int。
根本原因;本身是构造函数,在对其进行调用的时候使它变为普通函数。而普通函数需要返回值,构造函数不需要。但是我们没有返回return
value所以函数默认返回None。
重点:构造函数不能,也不需要返回任何值
5.self保存不同对象的特征值
定义实例方法时,需要有self这个参数。调用时候不需要对self传参。
class Array2:
'''
类里面的变量我们称做
类变量
'''
data = 'ring02'
size = 2
def __init__(self, data, size):
'''
构造函数,基本是通用的,包括php,java都有构造函数
构造函数作用,初始化对象属性
对象中的变量,方法都属于属性
data,size都是实例变量
'''
data = data
size = size
def get_size(self):
print('get_size')
from c9_1 import Array1, Array2
arr2 = Array2([1,2,3,4,5], 5)
print(Array2.data)
结果:这里没有显示值
首先我们可以看值有没有传出,添加print查看
再次运行【打印出来值的,所有传出值了的】
造成上述情况原因;没有使用self保存传递的值
为此:
from c9_1 import Array2,Array3,Array4
arr3 = Array3([1,2,3,4], 4)
arr3.get_size()
arr3 = Array3([1,2,3,4,5,6], 6)
class Array3:
data = 'ring03'
size = 2
age = 11
def __init__(self, data1, size1):
self.data = data1
self.size = size1
"""
打印对象的属性
"""
def get_size(self):
print('data is {}'.format(self.data))
print('size is %d' % self.size)
def get_data(self):
print(self.data)
结果:
既然我们在类实例化的时候 传递进来不同对象的特征值
那么我们就需要保存不同对象的特征值
使用self保存对象的属性
self只和对象有关
谁调用了这个方法,self就与谁有关
self只和对象有关
和类无关
6.类变量和实例变量具体区别
from c9_1 import Array2,Array3,Array4
arr3 = Array3([1,2,3,4,5,6], 6)
print(arr3.__dict__)
print(arr3.size)
print(arr3.data)
class Array3:
data = 'ring03'
size = 2
age = 11
def __init__(self, data1, size1):
self.data = data1
self.size = size1
def get_size(self):
print('data is {}'.format(self.data))
print('size is %d' % self.size)
def get_data(self):
print(self.data)
dict:显示对象保存的所有属性
思考
在我们Array3数组类中定义,一个data和size是否合适?
我们Array3是一个类,这是一个模版
一个大而空的东西
在大而空的东西里面定义具体的data和size
这样明显是不合适的
7.动态添加与修改变量
class Array2:
'''
类里面的变量我们称做
类变量
'''
data = 'ring02'
size = 2
def __init__(self, data, size):
'''
构造函数,基本是通用的,包括php,java都有构造函数
构造函数作用,初始化对象属性
对象中的变量,方法都属于属性
data,size都是实例变量
'''
data = data
size = size
def get_size(self):
print('get_size')
from c9_1 import Array2,Array3,Array4
arr2 = Array3([1,2,3], 3)
# arr2对象动态添加lens变量
arr2.lens = 3
Array3.data = 'ring033'
print(arr2.__dict__)
print(Array3.__dict__)
print(arr2.data,arr2.size,arr2.lens, Array3.data)
结果:
发现对象属性本身是没有lens的变量的,但是添加了
另外Array3.data的值手动更改了后,显示的值也发送改变了
上述中 data = 'ring02’与size = 2 ;这两个属性与变量关系小时可以定义到类中,对象关系比较紧密就最好在构造函数中。
补充
想在对象里面(构造函数也算)访问类变量可以:print(self.class.data)
8.__name__在Python中的作用
python程序中一般都会有一个if条件句
if __name__ == '__main__':
当在有这个if条件句的模块中时,该程序会作为程序的入口,name__会强制改为__main
当在其他模块调用该模块时,__name__的值是该模块的文件名
9.构造方法也可以看作特殊实例方法
调用构造方法直接在类的实例化时候就可以调用,而调用实例方法,是通过(对象.方法)进行点用
arr.get_size
思考下在构造函数里面打印
实例变量self.data与data
结果是相同的吗
解释:
self.data与data真的是打印的同一个变量吗
尝试将形参data改为data1,再次进行尝试
self.data打印的对象中的实例变量 data打印的只是我们的形参
3.装饰器
lass Array5:
# 统计数组中所有元素的和
"""
AOP思想
"""
sum = 1
# 类变量,实例变量
def __init__(self, data, size):
'''
self.__class__.sum
Array5.sum
:param data:
:param size:
'''
self.data = data
self.size = size
@classmethod
def class_arr(cls):
cls.sum += 1
# print(self.data)
print(cls.sum)
"""
装饰器
"""
@staticmethod
def static_func1():
print('static')
def get_size(self):
# print(self.__class__.sum)
print('data is %s' % self.data)
print('size is %d' % self.size)
1.@classmethod:类方法
传递类:cls
from c9_1 import Array5
arr = Array5([1,2,3],3)
arr.get_size()
Array5.class_arr()
类方法
1.在实例方法中操作类变量
2.定义类方法(classmethod)
3.类方法作用顾名思义就是操作类变量 类方法中cls可以更改,但并不建议
4.类方法关联我们类本身,实例方法关联我们对象
各类方法
- __ new ()方法:是一种负责创建类实例的静态方法,他不需要使用staticmethod装饰器修饰,并且它优点于 init __ ()初始化方法被调用。
2. repr __()方法:显示属性
- __ del __()方法:销毁对象
- __ dir ()用法:列出地所有属性名
5. dict __()属性:查看对象内部所有属性名和属性值组成的字典
2.@staticmethod:静态方法
和类与对象关联小,基本为单个方法。【使用比较少】
3.公开,保护与私有
protected:保护,可以被子类进行调用
private:私有方法,只可以被自己调用,子类也不行。
public:公有的
保护与私有区别: 保护被子类调用 私有只能自己用
__【两个下划线默认为私有属性】】
class Array6:
'''
类里面的变量我们称做
类变量
'''
data = 'ring02'
size = 2
def __init__(self, data, size):
'''
构造函数,基本是通用的,包括php,java都有构造函数
构造函数作用,初始化对象属性
对象中的变量,方法都属于属性
data,size都是实例变量
'''
self.data = data
self.size = size
self.__price = 0
# self.price = 0
# desc我不希望别人在外部直接更改
def __modify_price(self, index):
if index < 0 or index > 100:
raise ValueError('range index error')
self.__price = index
print(self.__price)
def get_size(self):
print('data is %s' % self.data)
print('size is %d' % self.size)
def get_capacity(self):
print('capacity')
访问私有变量调用函数
from c9_1 import Array6
arr6 = Array6([1,2,3], 3)
print(arr6.__dict__)
print(Array6.__dict__)
arr6._Array6__price = 2
print(arr6.__dict__)
错误的修改方式
print(arr6.price)
arr6.get_size()
print(arr6.dict)
print(Array6.dict)
正确的修改方式
arr6.modify_price(2)
arr6.get_size()
私有方法,无法直接调用
print(arr6.dict)
print(Array6.dict)
arr6._Array6__modify_price(3)
4.子类给父类传值,需要使用super关键字
class Student1(Person):
def __init__(self, organization, name, skill):
self.organization = organization
"""
子类给父类传值,需要使用super关键字
"""
super().__init__(name, skill)
# def __init__(self, organization, name, skill):
# self.organization = organization
# super().__init__(name, skill)
def do_kill_monster(self):
pass
stu1 = Student1('英雄', 'king', '心脏引擎')
print(stu1.name)
print(stu1.skill)
print(stu1.organization)
如果我们子类完全继承父类 那么子类存在没任何意义
我们子类需要有一些不同于父类的变量,方法 这样才能最大程度发挥好继承作用
5.闭包
定义了函数和外部环境变量的结构为闭包,环境变量必须在函数外,且不可是全局变量,且外面一个函数的返回值是里面一个函数。它记住了自由变量的状态
闭包 = 函数+环境变量(函数定义时候)
注意:环境变量一定要在定义函数的外部,而且不能是全局变量
def demo1():
a = 3
def demo2(x):
return a*x*x
return demo2
a = 10
d = demo1()
上述函数d = demo1(),其实是用demo1()函数,把demo2(x)赋给d
添加函数print(d.__closure__)
闭包返回的是一个对象object,是将函数和环境变量都返回了
查看是否是闭包,还可以通过a.closure[index].cell_contents查看闭包中每个元组的值
添加函数print(d.__closure__[0].cell_contents)
返回的闭包的环境变量a = 3
对d赋值,
以下格式就是闭包:有外部环境变量,自由变量,内部的函数,引用自由变量,返回内部函数名称
def demo1():
a = 3
def demo2(x):
return a*x*x
return demo2
a = 10
d = demo1()
print(d(2))
6.列表生成式
列表常用的方法
1.append()方法:用于在列表末尾添加型的对象—语法:list.appandd()
2.count()方法:用于统计某个元素在列表中出现的次数—语法:list.count()
3.extend()方法:用于在列表末尾异性追加另一个序列中的多个值—语法:list.extend(seq)
4.index()方法:用于从列表中找出某个值第一个匹配项的索引位置—语法:list.index(x[, start[, end]])-----x:查找的对象;start:开始位置,end:结束位置
5.pop()方法:用于移除列表中的一个元素,默认为列表中的最后一个元素,并且返回该元素的值—语法:list.pop([index=-1])
6.remove()方法:用于移除李彪中某个值的第一个匹配项----语法:list.remove(obj)
7.reverse()方法:将元素倒序排列
列表生成式本质上就是for循环
aa = [i * i for i in range(1,5)]
print(aa)
遇见if else不能把if x % 2 == 0 else -x放后面只能放前面
fff = [x if x % 2 == 0 else -x for x in range(1,10)]
print(fff)
7.生成器generator
将列表[]改为()即可称为生成器
只要把一个列表生成式的[]改成(),就创建了一个generator
generator保存的是算法 每次调用next(g),就计算出g的下一个元素的值,
直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误
一直用next调用【一步一步的调用】,一定不是一个好办法,我们需要用for来调用 for可以将StopIteration处理 因为生成器也是一个可迭代对象,它进行惰性匹配
惰性匹配,循环一次算一次。这样循环时开始计算节省内部空间
ll = (x * x for x in range(10))
print(next(ll))
print(next(ll))
print(next(ll))
print(next(ll))
上述表达可以改为for循环
ll = (x * x for x in range(10))
for i in ll:
print(i)
使用循环好处在,它会在范围超过的时候会捕获错误不会报错会直接输出。
报错实例:
ll = (x * x for x in range(3))
print(next(ll))
print(next(ll))
print(next(ll))
print(next(ll)
yield命令:可以将正常数列变成生成器,他可以从中断的位置继续运行。
generator函数和普通函数的执行流程不同,普通函数遇到return语句或者最后一行函数语句就直接返回,但是generator函数再用next()调用执行的时候,遇到yield语句也会返回,但是再次执行的时候会从上此次返回的yield语句处执行。
对于yield的理解,可以理解为是特殊的return关键字
当执行到yield i时,返回了i的值,并保存了此时函数的状态,当使用next调用这个生成器函数时,就会从刚刚返回值的时候继续函数的执行
8.迭代器
迭代对象和迭代器next
可迭代对象,可以被for循环的数据-----迭代器iter(),iter(),-------生成器 yield [] ()
可迭代对象:字符串、元组、列表、字典、set(在定义中最好放一个数组;set最主要的功能是可以去重)
生成器就是一种迭代器,可以被next调用并不断返回下一个值的对象称为迭代器:iterator。
优先级:generator生成器 > itertor > iterable
9.高阶函数
1)匿名函数
使用lambda关键字修饰的简单函数
lambda x,y: x>y?x:y
def add_demo(x,y):
return x + y
def print_str(x):
return x
f = lambda x, y : x + y
print(f(2,3))
2)map(__func, __iter1)
__func函数:传入函数值与函数名
__iter1函数:处理
map传入第一个参数式接受一个函数,第二个参数式一个可迭代对象,结果返回一个迭代器。
即:使用__iter1迭代器执行__func函数
3)reduce(__func, __iter1)
与map相似都是使用__iter1迭代器执行__func函数
不同与map:将上一次计算的结果作为下一次计算的参数
4)filter(__function,__iterable)
用__function函数过滤,__iterable中的元素
5)sorted(__iterable,key,reverse)
依据key的值排序__iterable中的元素,reverse决定是否逆序