zoukankan      html  css  js  c++  java
  • python—类的继承——定制类

    python中继承一个类

    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender

    定义Student类时,只需要把额外的属性加上,例如score:

    class Student(Person):
        def __init__(self, name, gender, score):
            super(Student, self).__init__(name, gender)
            self.score = score

    一定要用 super(Student, self).__init__(name, gender) 去初始化父类否则,
    继承自 PersonStudent 将没有 namegender
    函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用__init__()方法,
    注意self参数已在super()中传入,在__init__()中将隐式传递,不需要写出(也不能写)。
     

    python中判断类型

    函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。

     print isinstance(t,Person)
    print isinstance(t,object)
    print isinstance(t,Student)
    print isinstance(t,Teacher)

    一个父类的实例不能是子类类型,因为子类比父类多了一些属性和方法。

    一个实例可以看成它本身的类型,也可以看成它父类的类型。

     

    python中多态

    sStudent类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

    Python提供了open()函数来打开一个磁盘文件,并返回 File 对象。File对象有一个read()方法可以读取文件内容:

    例如,从文件读取内容并解析为JSON结果:

    import json
    f = open('/path/to/file.json', 'r')
    print json.load(f)

    由于Python的动态特性,json.load()并不一定要从一个File对象读取内容。任何对象,只要有read()方法,就称为File-like Object,都可以传给json.load()

    请尝试编写一个File-like Object,把一个字符串 r'["Tim", "Bob", "Alice"]'包装成 File-like Object 并由 json.load() 解析:

    import json
    class Students(object):
        def read(self):
            return r'["Tim", "Bob", "Alice"]'
    s = Students()
    print json.load(s)
     

    python中多重继承

    除了从一个父类继承外,Python允许从多个父类继承,称为多重继承

     
    class Person(object):
        pass
    class Student(Person):
        pass
    class Teacher(Person):
        pass
    class SkillMixin(object):
        pass
    class BasketballMixin(SkillMixin):
        def skill(self):
            return 'basketball'
    class FootballMixin(SkillMixin):
        def skill(self):
            return 'football'
    class BStudent(Student,BasketballMixin):
        pass
    class FTeacher(Teacher,FootballMixin):
        pass
    s = BStudent()
    print s.skill()
    t = FTeacher()
    print t.skill()
     

    python中获取对象信息

    拿到一个变量,除了用 isinstance() 判断它是否是某种类型的实例外,还有没有别的方法获取到更多的信息呢?

     可以用 dir() 函数获取变量的所有属性

        class Person(object):
                address = 'Earth'
                def __init__(self,name):
                         self.name=name
         p=Person('test')

         Person.age=25
         print (p.age)

         print ("dir:",dir(p))

         

    >>> dir(s)
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',
    '__hash__', '__init__', '__module__',
    '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
    '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
    'gender', 'name', 'score', 'whoAmI']

         如何去掉`__xxx__`这类的特殊属性,只保留我们自己定义的属性?回顾一下filter()函数的用法

       

    class Person(object):
        def __init__(self, name, gender, **kw):
            self.name=name
            self.gender=gender
            for k,v in kw.items():
                setattr(self, k, v)
    p = Person('Bob', 'Male', age=18, course='Python')
    print getattr(p, 'age')
    print p.course

     python中什么是特殊方法

       特殊方法是定义在class中的

       不需要直接去调这些特殊的方法

        python的某些函数或者操作符回去自动调用相应的特殊方法

     

    python中 __str__和__repr__

    如果要把一个类的实例变成 str,就需要实现特殊方法__str__()

     
    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
        def __str__(self):
            return '(Person: %s, %s)' % (self.name, self.gender)

    >>> p = Person('Bob', 'male')
    >>> print p
    (Person: Bob, male)
     

    python中 __cmp__

    对 intstr 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 __cmp__():

     
    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score
        def __str__(self):
            return '(%s: %s)' % (self.name, self.score)
        __repr__ = __str__
        def __cmp__(self, s):
            if self.score <s.score:
                return 1
            elif self.score > s.score:
                return -1
            else:
                if self.name < s.name:
                    return -1
                elif self.name > s.name:
                    return 1
            return 0
     
     
    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.score = score
    
        def __str__(self):
            return '(%s: %s)' % (self.name, self.score)
    
        __repr__ = __str__
    
        def __cmp__(self, s):
            if self.score == s.score:
                return cmp(self.name, s.name)
            return -cmp(self.score, s.score)
     
     

    python中 __len__

    如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。

    要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。

     

    例如,我们写一个 Students 类,把名字传进去:

    class Students(object):
        def __init__(self, *args):
            self.names = args
        def __len__(self):
            return len(self.names)

    只要正确实现了__len__()方法,就可以用len()函数返回Students实例的“长度”:

    >>> ss = Students('Bob', 'Alice', 'Tim')
    >>> print len(ss)
    3


    需要根据num计算出斐波那契数列的前N个元素
    class Fib(object):
        def __init__(self, num):
            self.num = num
            self.L = [0,1]
            for n in range(num-2):
                next_num = self.L[n]+self.L[n+1]
                self.L.append(next_num)
           
        def __str__(self):
            return str(self.L)
           
        def __len__(self):
            return self.num
    >>>f = Fib(10)
    >>>print f
     
    方法二:
         
    def __init__(self, num):
            a, b, L = 0, 1, []
            for n in range(num):
                L.append(a)
                a, b = b, a + b
            self.numbers = L



     

    python中 @property

     给属性赋值怎么检查分数的有效性:

    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.__score = score
        def get_score(self):
            return self.__score
        def set_score(self, score):
            if score < 0 or score > 100:
                raise ValueError('invalid score')
            self.__score = score

    这样, s.set_score(1000) 就会报错。


    这种使用 get/set 方法来封装对一个属性的访问在许多面向对象编程的语言中都很常见。

    但是写 s.get_score()s.set_score() 没有直接写 s.score 来得直接。

    有没有两全其美的方法?----有。

    因为Python支持高阶函数,在函数式编程中我们介绍了装饰器函数,可以用装饰器函数把 get/set 方法“装饰”成属性调用:

    
    
    class Student(object):
        def __init__(self, name, score):
            self.name = name
            self.__score = score
        @property
        def score(self):
            return self.__score
        @score.setter
        def score(self, score):
            if score < 0 or score > 100:
                raise ValueError('invalid score')
            self.__score = score

    >>> s = Student('Bob', 59)
    >>> s.score = 60
    >>> print s.score
    60
    >>> s.score = 1000
    Traceback (most recent call last):
      ...
    ValueError: invalid score


    如果没有定义set方法,就不能对“属性”赋值,这时,就可以创建一个只读“属性”。
     

    python中 __slots__

    由于Python是动态语言,任何实例在运行期都可以动态地添加属性。

    如果要限制添加的属性,例如,Student类只允许添加 name、genderscore 这3个属性,就可以利用Python的一个特殊的__slots__来实现。

    顾名思义,__slots__是指一个类允许的属性列表:

    __slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。

     
    class Student(object):
        __slots__ = ('name', 'gender', 'score')
        def __init__(self, name, gender, score):
            self.name = name
            self.gender = gender
            self.score = score


    >>> s = Student('Bob', 'male', 59)
    >>> s.name = 'Tim' # OK
    >>> s.score = 99 # OK
    >>> s.grade = 'A'
    Traceback (most recent call last):
      ...
    AttributeError: 'Student' object has no attribute 'grade'



    class Person(object):
        __slots__ = ('name', 'gender')
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    class Student(Person):
        __slots__ = ('score')
        def __init__(self,score,name,gender):
            super(Student,self).__init__(name, gender)
            self.score=score
    s = Student('Bob', 'male', 59)
    s.name = 'Tim'
    s.score = 99
    print s.score


     

    python中 __call__

    在Python中,函数其实是一个对象:

    >>> f = abs
    >>> f.__name__
    'abs'
    >>> f(-123)
    123

    由于 f 可以被调用,所以,f 被称为可调用对象。

    所有的函数都是可调用对象。

    一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()

     

    我们把 Person 类变成一个可调用对象:

    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
    
        def __call__(self, friend):
            print 'My name is %s...' % self.name
            print 'My friend is %s...' % friend

    现在可以对 Person 实例直接调用:

    >>> p = Person('Bob', 'male')
    >>> p('Tim')
    My name is Bob...
    My friend is Tim...

    单看 p('Tim') 你无法确定 p 是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。

    class Fib(object):
        def __call__(self,num):
            a,b,L=0,1,[]
            for n in range(num):
                L.append(a)
                a,b=b,a+b
            return L
    f = Fib()
    print f(10)
       
  • 相关阅读:
    jmeterxpath的用法
    Jmeter中Websocket协议支持包的使用
    http 错误代码汇总
    Jmeter正则表达和xpath
    SSH Secure Shell Client安装和使用
    SecureCRT安装步骤
    DataRow转化成对象
    vb.net 与 c# 的switch ... case ...的一个重要区别
    DataRow 转换成Entity实例
    Sqlserver查找数据库中含有某字段的所有表
  • 原文地址:https://www.cnblogs.com/ting152/p/12976181.html
Copyright © 2011-2022 走看看