文章目录
Python知识盲点(三)
1. LEGB规则
Python在查找“名称”时,是按照LEGB规查找的:LocalEnclosedGlobal~Built in
- Local: 函数或者类的方法内部
- Enclosed: 嵌套函数(闭包)
- Global: 模块中的全局变量
- Built in: Python为自己保留的特殊名称
Python的面向对象
1.构造函数__init__()
用于进行实例化对象的初始化工作,其要点如下:
- 名称固定,必须是--init--()
- 第一个参数固定,必须是self
- 通常用来初始化实例对象的实例属性
- 通过“类名(参数列表)”来调用构造函数。调用后,将创建好的对象返回给相应的变量
- __new__()方法:用于创建对象,但我们一般无需重定义该方法
2.__dir__()
- dir(obj)可以获取对象的所有属性、方法
- obj.__dict__():对象的属性字典
- instance(对象,类型):判断对象是不是指定类型
3.类方法,静态方法
3.1类方法
类方法通过@classmethod来定义,格式如下:
@classmethod
def 类方法名(cls [, 形参列表]):
函数体
注意:
- 第一个cls必须有,cls指“类对象”本身
- 类方法
class Student:
company = "SXT"
@classmethod
def printCompany(cls):
print(cls.company)
Student.printCompany()
3.2静态方法
Python中允许你去定义和“类对象”无关的方法,称为“静态方法”
“静态方法”和在模块中定义的普通函数没啥太大区别。只是,静态方法由于写在了类当中,所以得通过类去调用
静态方法使用装饰器@staticmethod来定义.
4. 析构函数__del__()
没什么值得多说的
5.__call__(),可调用对象
class SalaryAccount:
def __call__(self,salary):
yearSalary = salary*12
daySalary = salary //22.5
hourSalary = daySalary//8
return dict(yearSalary = yearSalary,monthSalary=salary,daySalary =daySalary,hourSalary=hourSalary)
s = SalaryAccount()
print(s(3000)) # 执行s(3000)时,就会调用__call__()函数
6.方法的动态性
class Person:
def work(self):
print("Work")
#注意:这个函数不是Person类里的
def play_game(s):
print("{0}在玩游戏",format(s))
#这个函数也不是定义在Person类当中的
def work2(s):
print("work_2")
Person.play = play_game; # 给Person类动态增加一个对象
p = Person()
p.play() # 因为动态加了一个函数,所以不会报错
p.work() # work
Person.work = work2 # 把Person类当中的work函数修改为了work2
p.work() # work_2
7.私有属性和私有方法(封装)
Python没有很严格的Private 或者Public, 但是可以通过“__函数名,__属性名”来实现私有属性或者方法
class Employee:
def __init__(self,name,age):
self.name = name
self.__age = age # 这里的age便是私有属性
def __work(self): #私有方法
print("work")
e = Employee("Jack",18)
print(e.name) # Jack
#print(e.age) #会报错,因为age是私有的,没法公有访问
print(e._Employee__age) #18
e._Employee__work() # work
8. @property装饰器,get与set
@property 可以将一个方法的调用方式变成"属性调用"
-
在面向对象编程过程中,要熟练运用get与set方法
class Employee: def __init__(self, name, salary): self.__name = name #name为私有属性 self.__salary = salary#salary为私有属性 def get_salary(self): return self.__salary def get_name(self): return self.__name def set_salary(self,salary): self.__salary = salary emp1 = Employee("Jack",3000) print(emp1.get_salary()) # 3000 emp1.set_salary(10000) # 用这种方式实现对私有属性的修改 print(emp1.get_salary()) # 10000
-
上面那个代码,也可以修改为@property修饰
class Employee: def __init__(self, name, salary): self.__name = name #name为私有属性 self.__salary = salary#salary为私有属性 @property def salary(self): return self.__salary @property def name(self): return self.__name @salary.setter def salary(self,salary): self.__salary = salary emp1 = Employee("Jack",3000) print(emp1.salary0 # 3000 emp1.salary = 10000 # 用这种方式实现对私有属性的修改 print(emp1.salary) # 10000
9.重写__str__()方法
class Person: #默认继承object类
def __init__(self,name):
self.name = name
def __str(self):
return "name:{0}".format(self.name)
p = Person("Jack")
print(p) # name:jack
# 如果不重写__str__(), 那么,最后一行print出来的就是类对象的信息
10.mro函数
mro(Method Resolution Order)。我们可以通过mro()方法获得“类的层次结构“,mro的底层是广度优先搜索。
class A:
def aa(self):
print("aa")
def say(self):
print("say AAA!")
class B:
def bb(self):
print("bb")
def say(self):
print("say BBB!")
class C(B,A):
def cc(self):
print("cc")
c = C()
print(c.mro()) # [<class '__main__.C'>,<class'__main__.A'>,<class #'__main__.B'>,<class 'object'>]
11.super()获取父类定义
class A:
def say(self):
print("A",self)
class B(A):
def say(self):
super().say() # 相当于A.say(self)
print("B",self)
B().say() # <__main__.B object at ……>
# <__main__.B object at ……>
12.特殊方法,运算符重载
- 常见特殊方法
方法 | 说明 | 举例 |
---|---|---|
__init__ | 构造函数 | 对象创建:p = Person() |
__del__ | 析构函数 | 对象回收 |
__call__ | 函数调用 | p() |
__repr__, __str__ | 打印,转换 | print(a) |
__getattr__ | 点运算 | p.xxx |
__setattr__ | 属性赋值 | p.xxx = value |
__getitem__ | 索引运算 | a[key] |
__setitem__ | 索引赋值 | a[key] = value |
__len__ | 长度 | len(a) |
- 每个运算符实际上都对应了相应的方法
运算符 | 特殊方法 | 说明 |
---|---|---|
运算符+ | __add__ | 加法 |
运算符- | __sub__ | 减法 |
<,< =, == | __lt__, __le__, __eq__ | 比较运算符 |
>, >=, != | __gt__, __ge__, __ne__ | 比较运算符 |
|,^, & | __or__, __xor__, __and__ | 或,异或,与 |
<<, >> | __lshift__, __rshift__ | 左移,右移 |
*,/,%,// | __mul__,__truediv__,__mod__,__floordiv__ | 乘,除,取余,整数除 |
** | __pow__ | 指数运算 |
13. 特殊属性
特殊方法 | 功能 |
---|---|
obj.__dict__ | 对象的属性字典 |
obj.__class__ | 对象所属的类 |
class.__bases__ | 类的基类元组(多继承) |
class.__base__ | 类的基类 |
class.__mro__ | 类的层次结构 |
class.__subclasses__() | 子类列表 |
14.组合
class A:
def say_a(self):
print("a")
class B:
def __init__(self, a):
self.a = a
a = A()
b = B(a)
b.a.say_a() # a
Python的两种设计模式
其实设计模式有很多种,这两个比较典型
1.工厂模式
把很多对象通过一个类集中管理
class CarFactory:
def create_car(self,brand):
if band == "Benz":
return Benz()
elif band == "BYD":
return BYD()
elif band == "BMW":
return BMW()
else:
return "UnKnown"
class Benz:
pass
class BYD:
pass
class BMW:
pass
factory = CarFactory()
c1 = factory.create_car("Benz")
c2 = factory.create_care("BYD")
print(c1,c2)
2.单例模式
确保一个类只有一个实例,并且提供一个访问该实例的全局访问点
class MySingleton:
__obj = None #用来存储单例
__init_flag = True #确保实例只初始化一次
def __new__(cls,*args, **kwargs): #单例模式需要重写new方法
if cls.__obj == None:
cls.obj = object.__new__(cls)
return cls.__obj
def __init__(self, name): #单例模式通常也要重写init方法
if MySingleton.__init_flag:
self.name = name
MySingleton.__init_flag = False
a = MySingleton("aa")
b = MySingleton("bb")
#这样,虽然创建了两个对象,但是,内存中只会new一份,以及初始化一次