首页 > 编程语言 > 详细

python学习笔记八 面向对象相关(基础篇)

时间:2016-02-29 12:26:19      阅读:239      评论:0      收藏:0      [点我收藏+]

面向对象基本知识:

  • 面向对象是一种编程方式,此编程方式的实现是基于对 对象 的使用
  • 类 是一个模板,模板中包装了多个“函数”供使用(可以将多函数中公用的变量封装到对象中)
  • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
  • 面向对象三大特性:封装、继承和多态

面向对象类成员

技术分享

一、变量

变量包括:类变量和实例变量,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,

类变量:属于类

实例变量:属于实例

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)

由上述代码可以看出【实例变量需要通过对象来访问】【类变量可以通过类或实例访问】,在使用上可以看出类变量和实例变量的归属是不同的。其在内容的存储方式类似如下图:

技术分享

由上图可知:

  • 类变量在内存中只保存一份
  • 实例变量在每个实例中都要保存一份

应用场景: 通过类创建实例时,如果每个对象都具有相同的变量,那么就使用类变量。

二、方法

方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

  • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
  • 类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
  • 静态方法:由调用;无默认参数;
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)

由属性的定义和调用要注意一下几点:

  • 定义时,在普通方法的基础上添加 @property 装饰器;
  • 定义时,属性仅有一个self参数
  • 调用时,无需括号
               方法:obj.func()
               属性:obj.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]]()"""

 

python学习笔记八 面向对象相关(基础篇)

原文:http://www.cnblogs.com/koka24/p/5226786.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!