1、静态方法:只是名义上归类来管理,实际上在静态方法访问不了类或实例中的任何属性。
(1)我们先看以下代码,实例化一个对象后,d可以直接调用talk()
class Dog(object):
def __init__(self,name):
self.name=name
def talk(self):
print("%s is talking" % self.name)
d=Dog("chen")
d.talk()
(2)而我们在使用静态方法后,实例化后直接调用的话d.eat()会报错,因为在静态方法中,实例化的name是传递不进去eat函数中的;
class Dog(object):
def __init__(self,name):
self.name=name
@staticmethod #静态方法实际跟类没有关系,但是必须通过类名去调用;调用不了类的变量跟实例变量,相当于只是类的一个函数
def eat(self): #在实例化后是传不进来的,如果想要传进来,那么需要将d传进来
print("%s is eating %s" %(self.name,'包子'))
d=Dog("chen")
d.eat() #报错eat() missing 1 required positional argument: 'self',实例化后的self传不进去
所以我们这时候如果要访问eat()方法,则需要将实例传递给改函数,即
d.eat(d)
这样便可以将实例化对象d的name “chen”传递给eat函数。
2.类方法
类方法:只能访问类变量,不能访问实例变量。
如以下程序,我们将eat()方法定义为类方法,这时发现在实例化对象后,调用eat方法后报错,这时在构造函数中添加变量 self.n = 333,执行仍然报错,说明类方法,不能访问实例变量
class Dog(object):
def __init__(self,name):
self.name=name
self.n = 333
@classmethod #类方法,只能访问类变量,不能访问实例变量
def eat(self): #在实例化后是传不进来的,如果想要传进来,那么需要将d传进来
print("%s is eating %s" %(self.name,'包子'))
print("%s is eat %s" %(self.n,'包子'))
d=Dog("chen")
d.eat()
而我们在Dod类中添加两个类变量,这时再执行程序:
class Dog(object):
n=333
name="hhh"
def __init__(self,name):
pass
由上可知,类方法只能访问类变量
3.属性方法
属性方法:把一个方法变成一个静态属性,
(1)如以下程序:
class Dog(object):
def __init__(self,name):
self.name=name
@property #attribute
def eat(self):
print("%s is eating %s" %(self.name,'包子'))
d=Dog("chen")
#d.eat() #这样调用时报错,应该d.eat
d.eat # 属性方法:把一个方法变成一个静态属性
此时,eat方法为静态属性,所以d.eat()调用时会报错,我们需要这样来调用:d.eat
(2)A 这时eat是一个属性,没有办法通过括号来传递参数,这时如果要给eat传递参数,要写一个相同的eat函数,这时传递参数时便可以传递进来;
@eat.setter
def eat(self, food):
print("set to food:", food)
d=Dog("chen")
d.eat # 属性方法:把一个方法变成一个静态属性
d.eat="baozi" #如果要传递参数,必须在写一个相同的函数,@eat.setter
以上程序输出结果如下: 这时看到baozi被传递进来
chen is eating 包子
set to food: baozi
B 将以上给eat的赋值存储下来,在打印的时候发现输出结果发生变化:
class Dog(object):
def __init__(self,name):
self.name=name
self.__food=None
@property #attribute
def eat(self):
print("%s is eating %s" % (self.name, self.__food))
@eat.setter
def eat(self, food):
print("set to food:", food)
self.__food=food
d=Dog("chen")
d.eat # 属性方法:把一个方法变成一个静态属性
d.eat="baozi" #如果要传递参数,必须在写一个相同的函数,@eat.setter
d.eat
将传递给eat的参数“baozi”存下来:结果如下
chen is eating None
set to food: baozi
chen is eating baozi
(3)删除属性:再写一个相同的函数,删除;这时在调用d.eat报错
@eat.deleter
def eat(self):
del self.__food
print("删除完成")
del d.eat
d.eat #删除私有属性后,再次调用时报错
4.类的特殊成员方法:(以3的程序为例)
(1)__call__() 方法
__call__对象后面加括号,触发执行。
构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
将d实例化d=Dog("chen")后,再直接d()报错,这时我们在类Dog中写一个__call__()方法,
class Dog(object):
def __call__(self, *args, **kwargs):
print("running call",args,kwargs)
d=Dog("chen")
d() #d=Dog("chen") d(),与Dog("chen")()一样
d(1,2,3,name=333)
这时看到输出结果为:
running call () {}
running call (1, 2, 3) {'name': 333}
(2)__dict__()方法
没有实例化对象时,将类的方法以字典的形式打印出来,但是不包括实例的属性
#__dict__方法
print(Dog.__dict__) #没有实例化对象以字典的形式将类的方法打印出来,不包括实例属性
实例化对象后,打印对象的实例属性:
d=Dog("chen")
print(d.__dict__) #通过实例调用,只打印了所有的实例变量
输出结果如下:
{'name': 'chen', '_Dog__food': None}
(3)__str__方法:
如果我们直接实例化后打印,没有写str方法的话,输出的为内存地址
d=Dog("chen")
print(d) #如果没有str方法,打印输出为<__main__.Dog object at 0x01104B70>;如果写入str方法,在打印对象时,默认输出该方法的返回值
如果我们在类Dog中写入str方法,在实例化后打印,输出结果为该方法的返回值
def __str__(self):
return "<obj:%s>"%self.name
d=Dog("chen")
print(d) #如果写入str方法,在打印对象时,默认输出该方法的返回值:<obj:chen>