动态给对象添加属性和方法

动态给对象添加属性和方法

        • 成员方法:
        • 静态方法:
        • 类方法:

正常情况下,我们定义了一个class,创建一个class的实例后,我们可以给该实例绑定任何的属性和方法,这就是动态语言的灵活性。

动态给对象添加属性和方法:
class.属性名 = 属性值
class.方法名 = 函数

这里说的动态加属性和方法主要指的是关于 __slots__函数的使用
__ slots __ = (属性名,函数名)
功能:对动态添加的属性以及函数进行限制,只能添加元组中列举出来的属性名或者函数名
此限制当前类的实例起作用,对其子类不起作用.

class Person():
    #动态添加的属性以及方法进行限制
    #以元组的形式来进行列举,将能添加的所有的函数名或者属性名,以字符串的方式列举出来
    __slots__ = ("name","age","say",'speak')  
    # "name","age","say"'speak'限制实例的属性和方法,只允许有这几个
    # 不想无限制的任意添加属性和方法
    pass


if __name__ == "__main__":
    per = Person()
    
    #动态绑定属性
    per.name = "lili"
    per.age = 18
    print(per.name)
    print(per.age)
    # 打印结果
    lili
	18
	
	#动态给对象绑定函数
    def say():
        print("say hello")
    per.say = say
    per.say()
    # 打印结果
    say hello
'''
但是,给一个实例绑定的属性和方法对另外一个实例是不起作用的。
为了给所有的实例都绑定方法,可以通过给class绑定方法
'''  
	# 这些都会报错,因为per1上没有这些方法和属性
	per1 = Person()
	per1.say()
	print(per1.name)
	print(per1.age)

	# 动态给类增加属性
	Person.sex = "girl"
    print(Person.sex)#### 动态添加属性和方法
    per2 = Person()
    print(per2.sex)
    # 打印结果
    girl
	girl
	
	# 动态给类增加函数(方法)
	def speak(self, name):
		self.name = name
		print("my name is " + self.name)
	Person.speak = speak

	per3 = Person()
	per3.speak('lili')
	# 打印结果
	my name is lili

通常情况下,在类中定义的所有函数(注意了,这里说的就是所有,跟 self 啥的没关系,self也只是一个再普通不过的参数而已)都是对象的绑定方法,
对象在调用绑定方法时会自动将自己作为参数传递给方法的第一个参数。
除此之外还有两种常见的方法:静态方法和类方法,二者是为类量身定制的,但是实例非要使用,也不会报错。

成员方法:

通常情况下在类中定义的所有的函数,都是绑定在对象身上的,我们都称为成员方法.
成员方法是给对象准备的,因此我们需要使用对象来进行调用,不能使用类名.
使用的时机:
1.使用成员变量
2.使用其他的成员的方法的时候

class Student():
    def say(self):
        print("**********")

静态方法:

静态方法是一类特殊的方法,有时你可能需要写一个属于这个类的方法,但是这些代码完全不会使用到实例对象本身,比如:
静态方法是一种普通函数,位于类定义的命名空间中,不会对任何实例类型进行操作,python为我们内置了函数@staticmethod来把类中的函数定义成静态方法
调用此方法建议使用类名, [使用对象来进行调用也不报错]
使用的时机:
1.没有用到成员变量,也没有用类变量
2.没有用成员方法,也不使用类方法,还没有静态方法


class Student():
    @staticmethod
    def say(self):
        print("**********")
        
     @staticmethod
	def spam(x,y,z): #类中的一个函数,千万不要懵逼,self和x啥的没有不同都是参数名
        print(x,y,z)
        
 Student.say()
 Student.spam(1,23,3)

类方法:

类方法不是绑定到对象上,而是绑定在类上的方法。
类方法是给类用的,类在使用时会将类本身当做参数传给类方法的第一个参数,因此调用的时候,我们使用
类名来进行调用. [使用对象来进行调用也不报错]
python为我们内置了函数@classmethod来把类中的函数定义成类方法

class Test:
    x=1
    @classmethod
    def test(cls):
        print(cls,cls.x)
Test.test()

无论你用哪种方式访问这个方法,它总是绑定到了这个类身上,它的第一个参数是这个类本身

类方法中也含有一个隐式参数[声明的时候必须声明,但又无需手动传递的参数我们称之为隐式参数]
这个隐式参数代表类本身,通常使用cls来表示[于self类似]也是一种约定俗成的写法.

什么时候使用这种方法呢?类方法通常在以下两种场景是非常有用的:
1.使用到类变量/类方法,我们可以将此方法写成类方法
2.使用到静态方法的时候,我们可以将此方法写成类方法

'''
1.工厂方法:它用于创建类的实例,例如一些预处理。如果使用@staticmethod代替,
那我们不得不硬编码Pizza类名在函数中,这使得任何继承Pizza的类都不能使用我们这个工厂方法给它自己用。
'''
class Pizza():
    price = 20
    def __init__(self,taste):
        self.taste = taste
      
        
    @classmethod
    def getPrice(cls,size):
        return size*cls.price
'''
2.调用静态类:如果你把一个静态方法拆分成多个静态方法,除非你使用类方法,
否则你还是得硬编码类名。使用这种方式声明方法,Pizza类名明永远都不会在被直接引用,
继承和方法覆盖都可以完美的工作。
'''
class Pizza(object):
  def __init__(self, radius, height):
    self.radius = radius
    self.height = height

  @staticmethod
  def compute_area(radius):
     return math.pi * (radius ** 2)

  @classmethod
  def compute_volume(cls, height, radius):
     return height * cls.compute_area(radius)

强调,注意注意注意:静态方法和类方法虽然是给类准备的,但是如果实例去用,也是可以用的,只不过实例去调用的时候容易让人混淆,不知道你要干啥

使用静态方法与类方法的优点:
无需创建对象,可以直接使用类名来进行调用,使调用更加的方便.

结论:
区别,实例方法隐含的参数为类实例self,而类方法隐含的参数为类本身cls。 静态方法无隐含参数,主要为了类实例也可以直接调用静态方法。
所以逻辑上,类方法应当只被类调用,实例方法实例调用,静态方法两者都能调用。主要区别在于参数传递上的区别,实例方法悄悄传递的是self引用作为参数,而类方法悄悄传递的是cls引用作为参数。

你可能感兴趣的:(#,Python,基础知识)