python基础学习浅学类

小知识点:
面向对象和面向过程:::
(1)面向过程(亲力亲为): 煮饭,洗菜,洗碗,切菜,炒菜,出锅 吃饭
(2)面向对象(凡事都是对象来做):女朋友(煮饭,洗菜,洗碗,切菜,炒菜,出锅) 我们直接 吃饭
点外卖 吃饭

一.类 (抽象)

类是一个独立存放变量(属性/方法)的空间。(把一些事物的共有特点封装起来。)
实例也是一个独立存放变量的空间。(每个实例都是一个独立的变量空间,不同实例之间的空间不可见)

类名要大写,实例名要小写。

实例名.属性名 调用某一个实例属性。
类名.属性名 调用封装在类里面的类的属性。

类编码风格:
类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名
和模块名都采用小写格式,并在单词之间加上下划线。
对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的
功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,
对其中的类可用于做什么进行描述。
可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,
可使用两个空行来分隔类。
需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的 import 语句,再
添加一个空行,然后编写导入你自己编写的模块的 import 语句。在包含多条 import 语句的程序中,
这种做法让人更容易明白程序使用的各个模块都来自何方。

定义:
class 类名:
pass

1.例如:
class Person: #定义类名要首字母大写。
a = ‘两只手,两条腿’ #封装在类里面类中的属性
#类,是一个独立存放变量(属性/方法)的空间。

wumou = Person() #实例名 = 类名() 实例
zhangmou = Person()

wumou.name = “吴某” #实例的特征 实例属性 (一个实例的特征,就是属性)
wumou.age = 18
zhangmou.age = 20

print(Person.a) #调用类的属性
print(wumou.age) #调用实例属性

类与实例之间的关系:::
(1)类:::
是一类事物的抽象,不是真实存在的,描绘了该类事物的共性。
例如:“人”,“动物”
(2)实例:::
某类事物的具体个体,是该类事物的具体表现,它是真实存在的。
例如:“吴某”是具体的某个人,
“张某”也是具体的某个人。

2.私有属性:
在python中有两个私有属性,分别是在属性前加一个下划线()和两个下划线()
一个下划线外部可以直接访问,两个下划线外部不能直接访问。

一个下划线只是做简单的标记。
两个是私有属性,不能够直接使用。
python当中的私有属性没有绝对的私有。

class Person:
_sex = “男”
__age = 18

wuhan = Person() #实例

print(Person._sex) #调用类属性
print(Person.__age) #双下划线会报错,不可以直接访问双下划线变量名
print(Person._Person__money) #这样就可以访问双下划线的属性

###在python中,_和__的使用更多的是一种规范/约定,没有真正限制的目的###
###定义类中的私有属性也可以被子类继承###

小知识点:::
dir() 可以查看方法,里面可以放类名。

3.类里面的方法
方法就是封装在类里面的一种特殊函数。

例:
class Person:
def sing(self): #方法,在类里面写函数叫做在类里面定义方法。
print(“我最帅!”) #里面有一个默认值none。 print(“我最帅!”,none)

wuhan = Person() #定义实例,写类必备。

wuhan.sing() #调用类里面的方法。 格式:实例化对象.方法()
Person.sing(self = ‘要传入的东西’)

实例方法 的调用过程和 self:::
(1)self:通常,将默认会传入的那个参数命名为self,用来表示调用这个方法的实例对象本身。
(2)实例方法:方法总是定义在类中,但是却叫“实例方法”,因为它表示该类所有实例所共有的行为。

小知识点:::self指的是实例,谁去使用它,那么它就是谁。
例:
class Person:
def sing(self):
print(“老师在唱歌%s”%self.geci)
print(id(self)) #会发现此处的self的id和下面的laoshi的id是一样的
laoshi = Person() #在这个实例中,laoshi使用了self,所以self就是laoshi
print(id(laoshi))
#和函数的传参一样,只是会先传一个自身的实例self

laoshi.geci = “温暖了寂寞”

laoshi.sing()

  1. init 双下划线
    初始化方法,作用是在实例化的时候,自动调用。(魔法方法)

“初始化”特殊方法:
在Python中有很多以双下划线开头且以双下划线结尾的固定方法,它们会在特定的时机被处罚执行。
__init__就是其中之一,它会在实例化之后自动被调用。以完成实例的初始化。

可以在创建对象时,为对象实现一些初始化的操作,提供一些默认值,需要为类定义实例属性的时候才会执行__init__方法。

class Person:
def init(self.name):
self.name = name #self.name是实例属性;name是方法。

 def sing(self):
	 print('吴某最帅')

wumou = Person(“吴某”) # 实例化 自动调用我们的初始化方法,把吴某这个名字给了name
(这句代码意味着 wumou.name = “吴某”(定义一个实例属性) wumou.name相当于self.name,"吴某"相当于给了name)

魔法方法:每一个魔法方法都有它特定的功能。

小知识点:
在python中,指向被删除了,就会被回收。
del删除指向,一个变量指向没有了就会被回收。
del调用的就是__init__魔法方法。
例如:列表方法中,del 列表名,再查看这个列表的时候就会报错,因为del把指向删除了。

del 析构,也叫销毁初始化方法(销毁上面的那个),是在这个文件运行完然后触发。(魔法方法)

__del__就是一个析构函数,当使用del删除对象时,会调用它本身的析构函数。提示开发者,对象被销毁了,方便调试,进行一些必要的清理工作
浅显点理解就是:(当实例对象引用数为0的时候就会调用这个魔术方法)
即当类里面使用了del魔法方法的时候,如果使用了del删除,那么就会调用__del__魔法方法;如果没有使用del删除,那么在程序的最后,会自动回收内存地址,就会调用__del__魔法方法。

入门:
class Person:
pass

hansha = Person()
print(hansha) #输出为:hansha这个实例化的对象指向的对象。即为:<main.Person object at 0x00000175C3AFC1D0>
del hansha
print(hansha) #输出会报错,因为指向被删除了。即为:NameError: name ‘hansha’ is not defined

稍微升一点级:
python中一个程序执行完了,内存空间就会被回收,回收掉那么指向就没有了。
class Person:
def del(self): #相当于重写了python的__del__方法。在列表里使用del删除时调用的是python默认的__del__方法。
print(‘好好学习’)

hansha = Person()
print(11111)
print(22222)
输出为:
11111
22222
好好学习

来个对比的例子仔细看看:
当指向删除完了之后会调用__del__魔法方法。
class Person:
def del(self):
print(‘好好学习’)

hansha = Person()
print(11111)
del hansha
print(22222)
输出为:
11111
好好学习
22222

总结的高级版:
基于变量计数的对象销毁机制
当没有一个变量指向某个对象的时候,python会自动销毁这个对象,以便回收内存空间。
del关键字,可以删除一个变量的指向。
class Person:

def __init__(self,name):    #初始化方法
	self.name = name

def __del__(self): 			#析构方法(销毁方法)
	print(self.name,"被销毁了")

wuhan = person(“无名”)
del wuhan #输出为:被销毁了

这里为引用了《python编程从入门到实践》
二,
继承:

例子:
class Car():
“”“一次模拟汽车的简单尝试”""
def init(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = str(self.year) + ’ ’ + self.make + ’ ’ + self.model
return long_name.title()
def read_odometer(self):
print(“This car has " + str(self.odometer_reading) + " miles on it.”)
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print(“You can’t roll back an odometer!”)
def increment_odometer(self, miles):
self.odometer_reading += miles

class ElectricCar(Car):
“”“电动汽车的独特之处”""
def init(self, make, model, year):
“”“初始化父类的属性”""
super().init(make, model, year)
#让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
如:self.battery_size = 70

我们还添加了一个名为 describe_battery() 的方法,它打印有关电瓶的信息

( def describe_battery(self):
“”“打印一条描述电瓶容量的消息”""
print("This car has a " + str(self.battery_size) + “-kWh battery.”)
my_tesla = ElectricCar(‘tesla’, ‘model s’, 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery() )

my_tesla = ElectricCar(‘tesla’, ‘model s’, 2016)
print(my_tesla.get_descriptive_name())

首先是 Car 类的代码。创建子类时,父类必须包含在当前文件中,且位于子类前面。
我们定义了子类 ElectricCar 。定义子类时,必须在括号内指定父类的名称。方法 init()
接受创建 Car 实例所需的信息。

super() 是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用
ElectricCar 的父类的方法 init() ,让 ElectricCar 实例包含父类的所有属性。父类也称为超
类(superclass),名称super因此而得名。也可以直接Car.init()。
在子类中调用父类的初始化方法格式是:父类名.init(self) 但是super是直角包括所有父类,但是父类名的需要一个个写。

为测试继承是否能够正确地发挥作用,我们尝试创建一辆电动汽车,但提供的信息与创建普
通汽车时相同。我们创建 ElectricCar 类的一个实例,并将其存储在变量 my_tesla 中。这
行代码调用 ElectricCar 类中定义的方法 init() ,后者让Python调用父类 Car 中定义的方法
init() 。我们提供了实参 ‘tesla’ 、 ‘model s’ 和 2016 。
除方法 init() 外,电动汽车没有其他特有的属性和方法。当前,我们只想确认电动汽车
具备普通汽车的行为:

2016 Tesla Model S

#####1.
重写父类的方法:
对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子
类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方
法,而只关注你在子类中定义的相应方法。

多继承中super调用所有父类的被重写的方法。super本质是用mor算法的顺序调用的。

父类也称为基类。

######2.
导入类:
Python允许你将类存储在模块
中,然后在主程序中导入所需的模块。

将 Car 类存储在一个名为car.py的模块中,使用该模块的程序都必须使用更具体的文件名,如my_car.py,其中只包含 Car 类的代码。
我们包含了一个模块级文档字符串(在该模块的最上面),对该模块的内容做了简要的描述。你应为自己
创建的每个模块都编写文档字符串。

下面来创建另一个文件——my_car.py,在其中导入 Car 类并创建其实例:

from car import Car #从一个只包含一个类的模块中导入这个类

from car import ElectricCar #从一个包含多个类的模块中导入一个类

from car import Car, ElectricCar #从一个有多个类的模块中导入多个类

import car #导入整个模块 我们使用语法 module_name.class_name 访问需要的类

from module_name import * #导入模块中的所有类 (不建议使用,如果要用,推荐使用导入整个模块)

import 语句让Python打开模块 car ,并导入其中的 Car 类。这样我们就可以使用 Car 类了,
就像它是在这个文件中定义的一样。

######3.
继承:
可以处理功能的迭代更新,以及拓展
重用代码,方便代码的管理和修改。

类名.bases 可以查看类的父类有哪些,注意要print。

每一个类,如果你不写继承,那么这个类继承的就是object。
class Father(object): #object默认自动创建了__init__初始化方法
#父类
pass

fa = Father() #实例,自动调用父类的__init__ 初始化方法就叫做继承。

例子:
class Father: 父类

def eat(self):
	print('大吃一顿')

class Son1(Father): #子类Son1继承父类Father
pass

hansha = Son1()
hansha.eat() #子类Son1可以使用父类Father中的eat方法。

高级的来咯!!!
多继承:::
多继承优先级:从左往右,优先级由高到低。
如果继承的两个父类有同样的方法,那么会选择优先级高的方法,即子类会优先使用最先被继承的方法。
class Father:
def init(self,name,age):
self.name = name

def eat(self):
	print('大吃一顿')

class Mother:
def init(self,name,age,sex):
self.name = name

def cook(self):
	print('做菜')

class Son(Father,Mother):
pass

hansha = Son(‘寒沙’,18)
hansha.eat()
hansha.cook()

最高级的来啦!!!

class Base:
def play(self):
print(‘这是Base’)

class A(Base):
def play(self):
print(‘这是A’)
super().play() #这里调用的是B

class B(Base):
def play(self):
print(‘这是B’)
super().play() #这里调用的是Base

class C(A,B):
#当子类继承父类之后,如果子类不想使用父类的方法,可以通过重写来覆盖父类的方法
def play(self):
print(‘这是C’)
# #重写父类方法之后,如果又需要使用父类的方法:
# B().play() #第一种方法 实例化,再使用方法
# A.play(self) #第二种方法 类名使用这个方法
super().play() #这里调用的是A
c = C()
c.play()
print(C.mro) #可以通过调用类的__mro__属性或者mro方法来查看类的继承关系
#输出为(<class ‘main.C’>, <class ‘main.A’>, <class ‘main.B’>, <class ‘main.Base’>, <class ‘object’>)

#super可以使用父类的方法;在父类中也可以使用super函数;要满足mro算法规则
#根据mro的顺序来决定调用的是谁

#在python3中,类被创建时会自动创建方法解析顺序mro

######4.
mro顺序 算法 保证程序能够按序执行。

mro顺序的作用:
#保证所有的类在用(构造)他的时候只被用(构造)一次!
保证多继承的时候,每个类只出现一次。
super().init() 相当于使用了mro。

#######6.
定制属性访问 (增,删,改,查)
就是对类里的属性进行增删改查的操作
(1)增
setattr(实例名,“属性名”,值) 或者 实例名.属性 = 值

(2)删
delattr(实例名,“属性名”) #只能删除自己家的属性

(3)改
setattr(实例名,“属性名”,“新属性”) #有这个属性才可以修改

(4)查
hasattr(实例名,“属性名”) #返回布尔值,有就True,没有就False
或者
getattr(实例名,“属性名”) #存在就能取到这个值,不存在就报错

可以用成 实例名.getattr(“属性名”) 上面的几个也可以(因为在python里面已经定义好了,已经有源码),但是hasattr不可以,没有这个方法。
但是用这种方法时,要在类里面定义这种方法。(重写方法)
例如:
def getattribute(self,item):
return “属性不在”
把这个写在类里面作为一个方法。
重写一个源码,python会返回你重写的这个方法的返回值,而不会再执行源码。

举例说明:
class Rectangle:
#__init__不能使用return
def init(self,length,width):
self.length = length
self.width = width

def area(self):
    #使用self 那个实例去使用它,它就是谁
    return(self.length*self.width)

a = Rectangle(4,5)
################查
#判断实例有没有这个属性
print(hasattr(a,‘length’)) #输出aTrue
#实例的这个属性值是什么 获取值,没有就报错
print(getattr(a,‘length’)) #输出4

################改
setattr(a,‘width’,50) #本来应该是5,现在改成了50
#还可以写成: re .setattr(‘width’, 50)
print(getattr(a,‘width’)) #输出就是50

################增
#第一种:
#setattr 有则改,无则增
print(hasattr(a,‘name’)) #在这里实例a里面没有属性name。输出False
setattr(a,‘name’,‘hansha’) #没有就增加属性name
#还可以写成:a.setattr(‘name’, ‘hansha’)
print(hasattr(a,‘name’)) #上一句增加了name属性。输出True
#第二种:
a.age = 18

################删
print(getattr(a,‘age’)) #因为上面增加了属性age。输出为True
delattr(a,‘age’) #删除属性age
#还可以写成:a.delattr(‘age’)
print(getattr(a,‘age’)) #上面删除了属性age。输出为False

(1) + 调用的是__add__

class A:
def init(self,num1,num2):
self.num1 = num1
self.num2 = num2

def __add__(self,other):      #self  实例对象   ;   other  另外一个实例对象
	sum1 = self.num1 + other.num1
	sum2 = self.num2 + other.num2
	return sum1,sum2

a = A(1,2)
b = A(3,4)
print(a+b) #输出为 (4,6)

运算符方法(了解即可)
add(self,other) # x+y
sub(self,other) # x-y
mul(self,other) # xy
mod(self,other) # x%y
iadd(self,other) # x+=y
isub(self,other) # x-=y
radd(self,other) # y+x
rsub(self,other) # y-x
imul(self,other) # x
=y
imod(self,other) # x%=y

(2)在交互模式下输出的交互信息与直接print的信息有些不同,
背后的原理是 ?
str和repr原理:

return返回的必须是字符串。
print打印实例对象的时候(没有重写__repr__方法,直接是pass)显示的是 地址
如果重写了__repr__方法,那么打印的就是__repr__方法里面的东西
如果同时重写了__repr__和__str__方法,打印实例对象的时候,只会显示__str__里面的内容
例一:::
class Person:

def __repr__(self):
	return '这是一个repr方法'

def __str__(self):
	return '这是一个str方法'

p = Person()
print§ 输出为: 这是一个str方法

%s 使用的是__str__方法; %r 使用的是__repr__方法
例二:::
class Person:

def __repr__(self):
	return '这是一个repr方法'

def __str__(self):
	return '这是一个str方法'

p = Person()
print(’ %s’%p) 输出为:这是一个str方法
print(’ %r’%p) 输出为:这是一个repr方法

在python中,str和repr方法在处理对象的时候,分别调用的是对象的__str__和__repr__方法
print打印对象,调用str函数,如果对象没有定义__str__方法,则调用__repr__方法处理
在交互模式下,直接输出对象,显示 repr 的返回值

(3) 魔术方法 def call(self)
正常情况下,实例是不能像函数一样被调用的,要想实例能够被调用,就需要定义 call 方法
class Person:

def a(self):
	print('this is a ')

#实例对象加上括号就会自动调用call方法
def __call__(self,*args,**kwargs):
	print('this is call')

p = Person()
p() #输出为: this is call

拓展:
类中的一些查询相关信息的方法(了解既可)
1、class 查看类名

格式:  实例.__class__

2、dict 查看全部属性,返回属性和属性值键值对形式

格式:实例.__dict__

3、doc 查看对象文档,即类中(用三个引号引起来的部分)

格式:类名.__dict__

4、bases 查看父类

格式:类名.__base__

5.mro 查看多继承的情况下,子类调用父类方法时,搜索顺序

格式:子类名.__mro__

          	              实例.__class__.__mro__

(4)再来个魔术方法
类每次实例化的时候都会创建一个新的对象,如果要求类只能被实例化一次该怎么做呢?
__new__方法

举个例子:::
class Person:

#初始化
def __init__(self):
    print('this is init')

def __new__(cls, *args , **kwargs):
    print('这new方法在init之前就进行了调用')
    #重写new方法
    #new方法是最先被调用的
    #new 必须返回父类的new方法,程序才能继续往下运行,如果不返回,即没有下面这行程序就不会往下运行。
    return super().__new__(cls)

hansha = Person()

四个点理解__new__方法:
1、__new__方法是在类创建实例的时候
自动调用的。
2、实例是通过类里面的__new__方法是在
类 创建出来的。
3、先调用__new__方法创建实例,再调用 __init__方法初始化实例。
4、__new__方法,后面括号里的cls代表
的是类本身

在上面的例子中,我们可以看到创建实例的时候,自动调用了__new__,方法和__init__方法,并且
是先调用的__new__(__new__方法会在内存当中开辟一个空间)再调用的__init__方法,打印 cls 的时候显示的这个Person类

#######
new方法会开辟空间
每次实例化,这个new方法都会开辟一个新的空间
可不可以让这new方法只开辟一个空间:::单例模式

单例模式:

提前引入一些小知识点:::
第一个:
hasattr() #has attribute
hasattr() 函数用于判断对象是否包含对应的属性
hasattr(object(对象),name(“字符串,属性名”))
返回True(有的时候) False(没有的时候)

class Person:
#范式:固定的公式;固定的写法
def new(cls,*args,**kwargs):
#hasattr 判断类里面有没有这个方法
#如果类没有instance这个属性
if not hasattr(cls,‘instance’): #cls就是Person这个类本身
#没有instance这个属性就会执行下面这句
#创建instance这个属性,等于父类的new方法
#new返回父类的new方法,和返回instance都可以
cls.instance = super().new(cls) #上面说如果类没有instance这个属性就执行这句,把父类的new方法添加为类本身的属性
#在下一句在return这个类本身的这个instance属性,这样在第二次实例化的时候,return
#的仍然是第一次实例化的cls.instance,就没有返回父类的new方法,也就没有创建新的内存
#空间,而是仍然指向第一次创建的内存空间
return cls.instance #如果把返回的改为 super().new(cls),直接返回父类的new方法,这就不是单例模式,因为每次实例化都会返回父类
#的new方法,即创建一个新的内存空间。
def init(self,name):
self.name = name

a = Person(‘寒沙’)
b = Person(‘敢敢’)
print(id(a))
print(id(b))

会发现两次的id都一样了,即两次指向同一片内存空间,相当于a被b覆盖了。
意味着这两个其实引用的是同一个实例,是一个实例的不同名字

(3)描述符
描述符协议:python描述符是一个“绑定行为”的对象属性,在描述符协议中,
它可以通过方法重写属性的访问。这些方法有__get__(), set(), 和__delete__()。
如果这些方法中的任何一个被定义在一个对象中,这个对象就是一个描述符

举例说明:
#描述符:描述符就是类里面的属性base
#控制实例对象a访问 这个属性 (base) 可以做一些额外的操作
#描述符 定义了__get__ set delete 当中的一种
class Base:
def get(self,instance,owner):
print(‘恭喜玩家获得荒古宝典’)
def set(self, instance,value):
print(‘强化%s’%value)
def delete(self,instance):
print(‘武器已经损坏’)

class A:
base = Base()

#实例化
a = A()

a.base # get 会直接输出__get__方法里面的内容

a.base = 50 # set 会直接输出__set__方法里面的内容

del a.base # delete 会直接输出__delete__方法里面的内容

(4)装饰器:
原因:python是一个动态语言,因为一切都是对象。是一个脚本语言。

#########################第一个:
首先咱再看遍闭包是啥:
#闭包
def fun1():
print(‘fun1’)
def fun2():
print(‘fun2’)
return fun2

#fun1()() ===> fun2()
a = fun1()
a() #会执行两个函数

然后,咱稍微高级点,看看闭包参数。这种方法比较麻烦,所以下面就引入了装饰器,和这个的功能一模一样,不过
简单了许多:
#闭包里面有参数 回调函数
def aa(fun): #fun = f1
print(’------------aa’)
def bb():
fun() #fun() = f1()
print(’----------bb’)
return bb

def f1():
print(‘this is f1’)

def f2():
print(‘this is f2’)

cc = aa(f1)
cc() #输出为 ------------aa
this is f1
----------bb

最后,就来看看第一种装饰器:

#装饰器 在不改变原有函数的基础上面增加额外的功能
#装饰器
def aa(fun): #fun = f1
print(’------------aa’)
def bb():
fun() #fun() = f1()
print(’----------bb’)
return bb

#装饰器 被装饰的函数名字(f1)会被当做参数传递给装饰函数(aa)
#代码就是: aa(f1)
#装饰函数(aa)执行完它自己内部的代码之后,会把它的结果返回给
#被装饰的函数(f1)
#代码就是: f1 = aa(f1)
#然后下面又是f1() 就相当于 aa(f1)()

@aa # 就相当于 f1 = aa(f1) 要使用嵌套函数里面的内容 aa(f1)(),就是最后调用的时候f1加个括号
# 而注意函数外部的只要用到装饰器就会执行,而嵌套的内层函数需要调用才会执行,所以
# 用处就是把重要的东西写到嵌套的内层函数,在调用的时候才会执行
def f1():
print(‘this is f1’)

def f2():
print(‘this is f2’)

f1() #输出和上面一个一模一样

############################第二个:
#类里面的内置装饰器
引入:

class Base:

def fun(self):
    print('好好学习,天天向上')

b = Base()
b.fun() # 调用类里面的方法,就会执行类里面的方法fun,打印 好好学习,天天向上

########
第一个是把类里面的方法变为属性:
class Base:
name = ‘寒沙’

@property         #将方法变为属性  更加简洁
def fun(self):
    return('好好学习,天天向上')

b = Base()
print(b.name) #属性的使用不需要加括号;方法的使用才要加括号
print(b.fun) #现在类里面的方法fun就变成了类的属性
#输出为:
寒沙
好好学习,天天向上

########
第二个是把类里面的方法变为静态方法,让其可以像使用函数一样去使用,而不需要再实例化才能使用:
class Base:

@staticmethod       #静态方法  方法能够像函数一样的去使用, 比如在类里面,你要写一些闭包什么的就可以在这里面写,相当于扩展了一些功能。
def fun2():              # 注意:这里已经不需要self   和class类断开联系
    print('过年好,新年好')

#再来个不加装饰器的
def func(self):
    print('这是普通方法')

Base.fun2() # fun2已经变为静态方法,可以像使用函数一样的使用
#输出为: 过年好,新年好

Base是类名;Base() 就是实例化
Base().func() # 而没有使用装饰器的方法就需要先实例化,才能去使用
#输出为:这是普通方法

########
第三个是类方法

class Base:

def func(self):
    print('这是普通方法')

@classmethod
def fun3(cls):        #没有self   和实例无关,这是类方法  ;   有self的是实例方法,需要先实例化才能使用
    print('cls类方法')
    cls().func()      #cls 代表类本身,即Base这个类

#类方法的使用,也不用实例化 直接类名点方法
Base.fun3()

###########################第三个:
#类装饰器 必须使用__call__方法
class Base:

def __init__(self,name):
    self.name = name

def __call__(self,*args,**kwargs):
    print('this is call')

@Base # func = Base(func) 被装饰函数(func)当做参数传递给装饰函数(Base)
def func():
print(‘this is func’)

func() # 此处的括号就相当于 func() = Base(func)()
# __call__方法只要实例化就会被调用
#输出为: this is call

看看高级点的:
class Base:

def __init__(self,fun):
    self.fun = fun

def __call__(self,*args,**kwargs):
    self.fun()         #就会打印    this is func
    print('this is call')

def __str__(self):
    return 'this is str'

@Base # func = Base(func) 相当于实例化 被装饰函数(func)当做参数传递给装饰函数(Base)
def func():
print(‘this is func’)

func() # 此处的括号就相当于 func() = Base(func)()
# __call__方法只要实例化就会被调用
print(func) # 打印类的实例,就会调用类里面的__str__方法

#输出为:
this is func
this is call
this is str

拓展一下呗:::
来个装饰器的习题:
测试type和isinstance两个函数,那个速度更加的快
#程序运行速度比较快 只查看上面两个
函数 运行一次的时间显示不出来效果
可以查看循环一万次的时间

#time.time() 计算目前的时间 时间戳(格林威治时间, 1970.1.1到现在的总秒数)
import time

def funa(fun):
def funb():
a = time.time()
fun()
b = time.time()
print(‘函数运行了%s’%(b-a))
return funb

@funa
def f1():
for i in range(100000):
type(1)
f1()
@funa
def f2():
for i in range(100000):
isinstance(1,int)
f2()

(3)多态
:提高了方法的灵活程度

class Student(object):
def print_uid(self):
print(“我是UID”)

class VIPStudent(Student):
print(“我是VIP学院”)

class PutongStudent(Student):
print(“我是普通学员”)

class BaianStudent(Student):
print(“我是卖课程的,为你们服务的”)

class Jiezhang(object):
def jiezhang(self,student:Student):
student.print_uid()

zhouzhanghong = Student() #实例化

baiyintao = VIPStudent()

cuihaolin = PutongStudent()

baian = BaianStudent()

check = Jiezhang()

check.jiezhang(zhouzhanghong)
check.jiezhang(baiyintao)
check.jiezhang(cuihaolin)
check.jiezhang(baian)

发布了14 篇原创文章 · 获赞 15 · 访问量 226

猜你喜欢

转载自blog.csdn.net/qq_44907926/article/details/104319991