面向对象基本知识:
面向对象类成员
一、变量
变量包括:类变量和实例变量,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,
类变量:属于类
实例变量:属于实例
class Role(object): #类变量,在内存中仅保存一份 ac = None def __init__(self,name,role,weapon,life_value): #实例变量,保存在各个实例中 self.name = name self.role = role self.weapon = weapon self.life_value = life_value def buy_gun(self,weapon): print("%s is buying [%s]" %(self.name,weapon)) self.weapon = weapon p1 = Role("p1",‘police‘,‘b12‘,100) t1 = Role("t1",‘tufei‘,‘b11‘,100) t2 = Role("t2",‘tufei‘,‘b13‘,100) t3 = Role("t3",‘tufei‘,‘b14‘,100) #实例赋值,将创建新的变量给实例 p1.ac = "China Brand" t1.ac = "US Brand" #类变量赋值,实例中没有创建该变量,继续使用类变量赋的值 Role.ac = "JP Brand" print("p1:",p1.weapon,p1.ac) print("t1:",t1.weapon,t1.ac) print("t2:",t2.weapon,t2.ac) print("t3:",t3.weapon,t3.ac)
由上述代码可以看出【实例变量需要通过对象来访问】【类变量可以通过类或实例访问】,在使用上可以看出类变量和实例变量的归属是不同的。其在内容的存储方式类似如下图:
由上图可知:
应用场景: 通过类创建实例时,如果每个对象都具有相同的变量,那么就使用类变量。
二、方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
class Foo: def __init__(self, name): self.name = name def ord_func(self): """ 定义普通方法,至少有一个self参数 """ # print self.name print(‘普通方法‘) @classmethod #类方法,不能访问实例变量 def class_func(cls): """ 定义类方法,至少有一个cls参数 """ print(‘类方法‘) @staticmethod #静态方法,只是放在类下面,不能访问类和实例属性 def static_func(): """ 定义静态方法 ,无默认参数""" print(‘静态方法‘)
相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。
不同点:方法调用者不同、调用方法时自动传入的参数不同。
三、属性
如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种。
对于属性,有以下三个知识点:
class foo(object): def __init__(self,name): self.name = name self.num = None #属性,将普通方法变成属性 @property def total_num(self): return self.num @total_num.setter def total_num(self,num): self.num = num print("total number is:",self.num) @total_num.deleter def total_num(self): print("total number got deleted") del self.num
#实例化 d = Animal("who") #调用属性
print(d.total_num) #属性赋值
d.total_num = 3 #删除属性
del d.total_num #报错num已经被删除
print(d.total_num)
由属性的定义和调用要注意一下几点:
注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。
四、类的私有化
类的所有成员都有两种形式:
定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
class Animal(object): def __init__(self, name): self.name = name #公有变量 self.__num = None #私有变量
访问限制:只有在类的内部可以访问。。。
class C(object): __name = "公有类变量" def func(self): print(C.__name) class D(C): def show(self): print(C.__name) #AttributeError: type object ‘C‘ has no attribute ‘_D__name‘ #print(D.__name) #AttributeError: type object ‘D‘ has no attribute ‘_D__name‘ C.__name #类访问,出错 obj = C() obj.func() #类内部可以访问 obj_son = D() #无法继承私有类属性 obj_son.show() #派生类访问,出错
class E(object): def __init__(self): self.__foo = "私有实例变量" def func(self): print(self.__foo) #类内部访问 class F(E): def show(self): print(self.__foo) #派生类访问 obj2 = E() obj2.__foo #通过对象直接访问,出错 print(obj2._E__foo) #访问私有实例变量 obj2.func() #类内部访问 obj2_son = F() obj2_son.show() #派生类中访问,出错
方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用,无法被继承
ps:非要访问私有属性的话,可以通过 对象._类__属性名
五、类的特殊成员
class foo(object): """ __doc__显示类的描述信息 """ def __init__(self): """ 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ; """ self.name = None self.age = None self.sq = [] def __call__(self): """ __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()() """ print("__call__") def __str__(self): """ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。 :return: """ return "啥" def __iter__(self): """ 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__ """ return iter(self.sq) def __del__(self): pass #def __new__(self): """ __new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。 一般不用使用这个方法,否则你将无法实例化对象 """ #pass
#实例化对象 f = foo() #自动执行__init__方法 f() #:对象() 或者 类()()调用__call__ foo()() #调用call方法 print(f.__doc__) #显示类的描述信息 print(f.__dict__) #类或对象中的所有成员 print(f) #方法输出__str__方法定义的返回值 for i in f:print(i) #类型内部定义了 __iter__,可以迭代
#test.py
import foo
obj = foo()
print(obj.__module__) # 表示当前操作的对象在那个模块
print(obj.__class__) # 表示当前操作的对象在那个类
print(isinstance(obj,foo))
五、反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,这四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
#反射实例 import sys class Webserver(object): def __init__(self,host,port): self.host = host self.port = port def start(self): print("Server is starting...") def stop(self): print("Server is stopping...") def restart(self): self.stop() self.start() #def test_run(name): # print("test running...",name) def test_run(self,name): #定义函数,setter添加该函数至实例方法 print("test running...",name,self.host) if __name__ == "__main__": server = Webserver("1.1.1.1",9999) server2 = Webserver("2.2.2.2",9999) #第三种实现 if hasattr(server,sys.argv[1]): #判断sys.argv[1]是否在对象中 func = getattr(server,sys.argv[1]) #获取server.method内存地址 func() #执行server.method() setattr(server,"run",test_run) #在该实例中添加方法runf方法名,test_run函数,无法为方法自动传入self #server.run("koka") #执行添加不带self参数的test_run,无法调用实例变量 server.run(server,"koka") #执行添加self参数的test_run,调用的时候需要手动添加实例 setattr(server,"root","koka") #该在实例中添加变量,同上 print(server.root) #调用实例变量 #print(server2.root) #其他实例无法调用 delattr(Webserver,‘start‘) #删除类中的start方法 print(server.restart()) """
判断用户输入是否存在实例
#第一种实现
if sys.argv[1] == "start":
执行server.start() #第二种实现 cmd_dic ={ "start":server.start, "stop":server.stop } if sys.argv[1] in cmd_dic: cmd_dic[sys.argv[1]]()"""
原文:http://www.cnblogs.com/koka24/p/5226786.html