1.实例属性和类属性
a.定义的位置不同:类属性直接定义在类中,实例属性定义在构造函数中
b.访问方式不同:实例属性必须用对象访问,类属性可以使用类名或者对象访问
c.在内存中出现的时机不同:类属性随着类的出现而出现,实例属性随着对象的出现而出现【在代码中,类优先于对象出现的】
d.调用的优先级不同:如果类属性和实例属性重名的情况下,对象优先调用实例属性
代码演示:
class Person(object): #1.定义的位置不同 # 类属性:直接定义在类中 name = "abc" num = 10 #实例属性:定义在构造函数中 def __init__(self,name): self.name = name #2.调用的方式 #类属性:对象.属性 或者 类名.属性 #实例属性;对象.属性 p = Person("javk") #3.优先级不同:实例属性的优先级高 print(p.name) print(Person.name) del p.name print(p.name) print(p.num) #总结;如果是多个对象的共享数据,则定义为类属性,如果是对象特有的数据,则定义为实例属性 #注意:尽量避免类属性和实例属性重名
2.动态添加属性和方法
代码演示:
from types import MethodType class Check(object): num = 0 __slots__ = ("num1","num2") def func(self): print("func") #1.动态绑定属性 c1 = Check() c1.num1 = 10 print(c1.num1) #2.动态绑定方法 """ def show(self): print("show") c1.func() #一个变量可以指向函数,该变量就可以被当做函数进行调用 c1.num2 = show #当对象调用一个成员函数的时候,self不需要手动传参的,参数表示的当前对象 c1.num2(c1) """ #使用系统的MethodType类创建一个函数 def show(self): print("show") # 参数:需要绑定的函数的名字 绑定给哪个对象 c1.num2 = MethodType(show,c1) c1.num2()
a.可以使用对象调用,也可以使用类名调用
b.类方法是属于整个类的,并不属于某个对象,所以在类方法中不能出现self
c.必须有一个参数,为cls,代表的是当前类,在类方法中可以直接通过cls创建对象,也可以通过cls直接调用当前类中的其他的类方法
静态方法:在一个类中,如果一个方法被@staticmethod装饰器修饰,则被称为静态方法
a.类似于类方法,可以使用对象调用,也可以使用类名调用
b.参数部分没有任何限定
代码演示:
class Check(object): #1.类属性 num1 = 0 def __init__(self,num2): #2.实例属性 self.num2 = num2 #3.成员函数:只能通过对象调用 def show(self): print("show") return 10 #4.类函数:对象或者类名调用 @classmethod def func1(cls): print("func~~~1",cls) #cls的用法;代表的是当前类,所以可以通过cls创建对象 c2 = cls(67) #通过cls创建出来的对象调用成员函数 c2.show() #5.静态方法:对象或者类名调用 @staticmethod def func2(): print("hgjhg") c1 = Check(76) c1.func1() Check.func1() #Check.show() #TypeError: show() missing 1 required positional argument: 'self' #print(type(c1)) c1.func2() Check.func2() #使用场景:类方法和静态方法 一般用于工具类的封装中
class SuperClass(object): @staticmethod def func2(): print("hgjhg") @classmethod def func1(cls): print("func~~~1") class SubClass(SuperClass): @staticmethod def func2(): print("子类~~~hgjhg") @classmethod def func1(cls): print("子类~~~~~func~~~1") s1 = SubClass() s1.func1() s1.func2() #结论:通过子类对象可以调用类方法和静态方法,同时也可以在子类中重写类方法和静态方法
__name__:获取类名的字符串
通过类名访问,对象访问会报错
__dict__:
通过对象访问:获取的是该对象的属性和方法,返回一个字典
通过类名访问:获取的是该类的所有的信息
__bases__:获取指定类的所有的父类
通过类名访问
代码演示:
#1.__name__ class Animal(object): num1 = 10 def __init__(self,name,age): self.name = name self.age = age @staticmethod def func2(): print("~~~hgjhg") @classmethod def func1(cls): print("~~~~~func~~~1") def func3(self): print("func3") a = Animal("abc",19) #print(a.__name__) #AttributeError: 'Animal' object has no attribute '__name__' print(Animal.__name__) #Animal #2.__dict__ print(a.__dict__) #对象.__dict__:实例属性 print(Animal.__dict__) #类名.__dict:该类中的所有的内容,除了实例属性 #3.__bases__:获取父类,返回是一个元组 #print(a.__bases__) #AttributeError: 'Animal' object has no attribute '__bases__' print(Animal.__bases__)