Python的一些基础知识点(三)

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一份,以及初始化一次

猜你喜欢

转载自blog.csdn.net/johnny_love_1968/article/details/115425179