函数变量作用域
a .在一个函数内创建一个变量时,默认情况下它是本地变量
b .在一个函数外定义一个变量时,它是全局变量
c .若在函数内读取一个全局变量时,不需加 global ,但要重新给全局变量赋值,需加 global ;若调用该变量的方法,则可以不用 global ,不算重新赋值
面向对象
1、面向对象:将一件事情首先想象为一个对象,然后提取该对象的所有共同的方法(动作)和属性(函数),利用这些方法和属性来完成该事情
好处:以对象作为程序的基本单元,将方法和属性封装其中,有三个特征:封装 继承 多态,提高重用、灵活、扩展
面向对象的特性:继承、封装、多态
封装:将对象的内部细节隐藏起来,通过公用方法来暴露该对象的具体功能
继承:子类继承父类(功能、属性)、还可以重写
多态:在继承的基础上对父类的某个行为复用的一种行为表现。(子类重写父类方法)
类:N多个对象抽取出具有相同属性和方法的对象的总称( Car 、 People )
对象:类的一个实例 car = Car()
2、面向过程:做一件事情,需要按照什么样的过程完成。大象装冰箱
python 里面自定义终极父类 object
self 作用:定义方法时表明当前方法是实例方法,定义要写 self ,调用不用。
类的组成
类属性:直接定义在类中,方法外的变量(通过类名.xx调用),每个实例都可调用
实例属性:定义在__init__方法中,使用self.xx表示(通过对象.xx调用)
实例方法:定义在类中的函数,自带self参数(通过对象.xx调用)
静态方法:@staticmethod修饰的方法(通过类名.xx调用)
类方法:@classmethod修饰的方法(通过类名.xx调用)
实例化对象后 : 实例 = 类名(),自动调用构造函数
实例对象三个特征:值value(所有属性、方法的集合)/地址id/类型type
每个函数后必加self参数,self叫做当前实例
类方法得传入类名或实例名调用,实例方法只能实例名调用。
从对象属性找,没有的话,找类里的
实例方法和类方法的区别:
定义方式不同、调用方式不同、权限不同
调用方式不同
①实例方法:只能用类的实例(对象)来调用,第一个参数总是 self ,调用时由 python (默认)自动传入当前调用该方法的实例。
②类方法:@ classmethod 修饰,默认认 cls 参数作为第1个参数,可以用类直解调用,也可实例调用,但类方法不能访问对象属性(self.***)、只能访问类属性。
权限不同:
实例权限高于类权限(所有人能做,则张3能做;张3能做,并不是所有人能做)
实例可以直接访问类属性和实例属性、实例方法、可以调用类方法
成员可见性:
左单下划线表示被保护,只有自己(本类)和子类可见
左双下划线表示私有,只有自己可见
左右双下划线是内置的默认方法,都有特殊作用
class Person:
#类属性,所有成员共享,定义在类中,方法外的变量
height = 180
name = "小明"
count = 0
def __init__(self,name,height):#name,height是方法的参数,是局部变量,作用域是整个__init__方法
#实例属性self.height = height, 将局部变量height赋值给实例属性self.height
#防止外部通过person.height篡改,故写成私有属性,读取的话,可以通过实例._类名__属性/方法读取,但不建议使用,所以换成定义get方法,修改的话定义set方法,,或者使用@propert装饰器变成属性
self.__height = height
self.__name = name
__class__.count += 1
print("我是第" + str(__class__.count) + "实例,我叫" + self.name)
def say(self):#定义在类中的函数,称为实例方法,自带self参数
print(f'I am: {self.name}')
return 'haha'
#获取私有属性的值
@property
def height(self):
return self.__height
def getHeight(self):
return self.__height
#修改私有属性的值
@height
def height(self,height):
self.__height = heght
def setHeight(self,height):
#检查入口参数的合法性
self.__height = height
@staticmethod
def height():
print('这是一个静态方法,不能调用实例属性和实例方法)
@classmethod
def classCount(cls):
print("一共实例了" + str(cls.count) + "个Person对象")
print('这是一个动态方法,不能调用实例属性和实例方法)
#
#Person.classSay()
person = Person('小米',189)
person.setHeight(175)
print(person.getHeight())
print(person.height)
#AttributeError: 'Person' object has no attribute '__height'
#print(person.__height)
什么时候定义类方法?实例方法?
—跟具体的某个实例没有关系的方法,一般来说我们定义成类方法,由类名直接词用。
—跟具体的某个实例有关,每个实例可能拥有不一样的方法,一般来说我们会定义成实例方法,由实例来进行访问
属性方法:可以像属性一样进行调用的方法(防止直接对属性的值进行修改)
魔法方法和特殊函数
obj.dict 对象的属性字典
obj.__class__对象所属的类
class.__bases__类的父类元组
class.__base__类的父类 若有多个父类,则输出最先继承的父类
class.__mro__类的层次结构 如:C类继承了A类,B类,object类
class.subclass()类的子类列表
_module
面向对象代码实现:
class Cat:
'''
这是猫的类
'''
def __init__(self,name,tail_length=10):
self.name = name
self.__privatename = name
self.taillen = tail_length
print("我是一只猫,我叫%s"%self.name)
def __del__(self):
print("我被系统回收了")
def __call__(self,*args,**kwargs):
#类的对象被调用,执行
print(args[0]+args[1])
def __str__(self):
return '我是%s'%self.name
def __len__(self):
return self.taillen
def __iter__(self):
return iter([1,2,3,4])
def __getitem__(self, key):
if key == 'name':
return self.name
else:
return None
def __setitem__(self, key, value):
if key == 'name':
self.name = value
def __delitem__(self, key):
if key == 'name':
del self.name
#可以进行数学运算加add 减sub 乘mul 除div 幂pow 余mod 比较lt、gt、eq、le、gt、ne、
def __add__(self, other):
if isinstance(other,Cat):
return [self,other]
elif isinstance(other,list):
other.append(self)
return other
cat = Cat('hao',15)
print(callable(cat))
# #__del__析构函数
print(cat)
#del cat
print(cat)
print(cat.__doc__)
print(cat.__dict__)
print(cat._Cat__privatename)
print(cat.__class__)
print(cat.__module__)
print(len(cat))
for i in cat:
print('cat',i)
cat1 = Cat('33')
cat2 = Cat('44')
print(cat1 + cat2)
cats = cat1 + cat2
cat3 =Cat('alen')
print(cat3 + cats)
print(cat['name'])
cat['name'] = 'li'
print(cat['name'])
# del cat['name']
# print(cat['name'])
实例化后,再动态赋值属性
class Person:
#类属性,所有成员共享
height = 180
def __init__(self):
pass
def say(self):
print("I am speaking")
return 'haha'
person = Person()
#person2 = Person()
#person.height = 175
#person2.height = 179
print(person.height)
print(person2.height)
print(Person.height)
print(person.__dict__)
print(person2.__dict__)
print(Person.__dict__)
__dict__显示类包含的属性
若对象没有该属性,则往类找
175
179
180
#{}
#{}
{'height': 175}
{'height': 179}
{'__module__': '__main__', 'height': 180, '__init__': <function Person.__init__ at 0x00000292B43B2EA0>, 'say': <function Person.say at 0x00000292B43B2F28>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
在实例化时传入实例属性
class Person:
# 类属性,所有成员共享
height = 180
name = "小明"
def __init__(self, height, name):
# 实例属性
self.height = height
self.name = name
def say(self):
print("I am" + self.name)
return 'haha'
@classmethod
def classSay(cls):
print("I am" + cls.name)
person = Person(185, '小宝')
Person.classSay()
print(person.height)
print(Person.height)
print(person.__dict__)
print(Person.__dict__)
使用类属性和类方法场景
class Person:
#类属性,所有成员共享
height = 180
name = "小明"
count = 0
def __init__(self,name,height):
#实例属性
self.height = height
self.name = name
Person.count += 1
print("我是第" + str(Person.count) + "实例,我叫" + self.name)
def say(self):
print("I am" + self.name)
return 'haha'
@classmethod
def classCount(cls):
print("一共实例了" + str(cls.count) + "个Person对象")
person1 = Person('小米',189)
person1 = Person('小侯',199)
Person.classCount()
#用__class__.count代替Person.count
继承(子类继承父类,可以有N个父类,若没继承类,默认继承oject)
class RichMan:
def __init__(self,money,company):
self.money = money
self.company = company
#需要导入父类模块中的RichMan类 ...
class RichChild(RichMan):
def __init__(self,money,company,mount):
super().__init__(money,company)
self.mount = mount
#子类与父类同名,先调用父类的init,确保父类初始化成功,但要是方法名与父类相同,则会直接覆盖
self.ownMoney = 0
object所有类直接或间接的父类
所有类都拥有object类的属性和方法
特殊方法:
new:由系统调用,用于创建对象(先__new__,再__init__)
init:
str:对象的描述,返回值是str类型,默认输出对象的内存地址
多态
指的就是"多种形态",即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用对象的方法。
在程序运行过程中根据变量所引用对象的数据类型,动态决定调用哪个对象中的方法。
Python 语言中的多态,根本不关心对象的数据类型,也不关心类之间是否存在继承关系,只关心对象的行为(方法)。只要不同的类中有同名的方法,即可实现多态
class Person():
def __init__(self,money,company):
self.money = money
self.company = company
def eat(self):
print('人吃五谷杂粮')
class Cat():
def eat(self):
print('猫喜欢吃鱼')
def fun(obj): #obj是函数的形式参数,在定义时不知道数据类型
obj.eat() #通过变量obj(对象)调用eat方法
person = Person()
cat = Cat()
fun(person) #Python 语言中的多态,根本不关心对象的数据类型,,只关心对象的行为(方法)
fun(ct)
深拷贝、浅拷贝
变量的赋值:只是形成两个变量,实际上还是指向同一个对象
浅拷贝:copy.copy(),拷贝时,对象包含的子对象内容不拷贝
深拷贝:copy.deepcopy(),源对象和拷贝对象的子对象也不相同
import copy
class CPU():
pass
class Disk():
pass
class Computer():
def __init__(self):
cpu = CPU()
disk = Disk()
com = Computer(cou,disk)
com1 = com
com2 = copy.copy(com)
print(com1,'子对象的内存地址:',com1.cpu,com1.disk)
com3 = copy.deepcopy(com)
推导式
针对序列:列表、元组、字符串
res1 = [x**2 for x in range(1,11)]
res2 = [x**2 for x in range(1,11) if x%2 == 0]
res3 = [x**2 for x in range(1,11) if x**2 %2 == 0]
#多重循环 + 判断
res5 = [x+y for x in 'python' for y in '123' if x+y != 'y1']
print(res5)
print(res1)
print(res2)
print(res3)
res4 = tuple(x**2 for x in range(1,11))
dic = {x:x**2 for x in range(1,11)}
ss = {x for x in range(1,11)}
print(res4)
print(dic)
print(ss)
模块module :一个包含所有你定义的函数和变量(.py)
导入:
1、import module
2、from module import funcname /*
包Package
1、from 包名.模块名 import 函数/变量
2、import 包名.模块名
3、from 包名 import 模块名 as 别名
主程序运行
if __name__ == '__main__':
pass
name__属性是每个 py 文件的一个内置属性,当这个文件是被直接执行时.值为__main;若作为包被导入,则值会变成文件名。
所以可以利用它来判断当前文件的使用方式,从而执行特定的代码。
场景:模块中写好函数和变量后,是需要进行调试的.为了避免导入时会执行调试,使用该方法。
Python的异常处理语法(异常捕获)
try:
程序执行语句块
except Exception as e:
异常处理语句块
else:
无异常时执行的语句块
finally:
最后执行的语句块
raise 主动抛出异常