python 类

1、方法

(1) 我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象:

class Person(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
    def get_grade(self):
        return 'A'
    
p1 = Person('Bob', 90)
print (p1.get_grade)   #<bound method Person.get_grade of <__main__.Person object at 0x000001D5D8ED7160>>
print (p1.get_grade())  # A

其实p1.get_grade 返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.get_grade() 才是方法调用

因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法

import types
def fn_get_grade(self):
    if self.score >= 80:
        return 'A'
    if self.score >= 60:
        return 'B'
    return 'C'
class Person(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
print (p1.get_grade())  # A
p2 = Person('Alice', 65)
print (p2.get_grade())
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
# 因为p2实例并没有绑定get_grade

 给一个实例动态添加方法并不常见,直接在class中定义要更直观  如:

class Person(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
        self.get_grade = lambda: 'A'

p1 = Person('Bob', 90)
print (p1.get_grade)    #<function Person.__init__.<locals>.<lambda> at 0x000001CA5B50A730>
print (p1.get_grade())  # A

(2)实例方法(普通方法)、类方法、静态方法的区别  请看:

class A:
    #类属性
    exp = "this is my programs"
    #实例方法或普通方法
    def normalMathod (self,name):
        print (self.exp)
    #类方法,可以访问类属性
    @classmethod
    def classMathod (cls,name):
        print(cls.exp)
    #静态方法,不可访问类属性
    @staticmethod
    def staticMathod (name):
        print (name)
a = A()
a.exp = "this is my"
a.normalMathod("exp")       # this is my
# A.normalMathod("exp")     # error
a.classMathod("exp")        # this is my programs  可以看出不管是类调用还是实例调用 类方法,访问的都是类属性
A.classMathod("exp")        # this is my programs
a.staticMathod("exp")       # exp
A.staticMathod("exp")       # exp

总结一张表 

 实例方法(普通方法)———————————————————随着实例属性的改变而改变

类方法(可类调用 也可实例调用)——————————————都是类属性的值,不随实例属性的变化而变化

静态方法(可类调用 也可实例调用)———————————— 不可以访问类属性,故直接输出传入方法的值

2 继承

(1)调用父类的构造函数的三种方法

(2)判断 t 实例是不是 Person类用: isinstance(t,Person)

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

(4)动态语言,静态语言

动态类型语言:指在运行期间才去做数据类型检查,也就是说,用动态语言编程时,永远不用去给任何变量去指定数据类型。该语言会在你第一次给该变量赋值的时候,在内部把数据类型记录下来。ruby或者Python是典型的动态类型的语言(这个我其实也不清楚,对这两门语言不太了解),一些脚本语言也多少属于动态类型语言。  

静态类型语言:指在编译期间就去做数据类型检查,也就是说在编码时要声明数据类型。 

动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。这是动态语言(例如python)和静态语言(例如Java)最大的差别之一

还有一个分类:
编译型语言:把做好的源程序全部编译成二进制代码的可运行程序。然后,可直接运行这个程序。
解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!
 java很特殊,java程序也需要编译,但是没有直接编译称为机器语言,而是编译称为字节码,然后用解释方式执行字节码。

(5)多重继承

除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用

①、继承两个互不相干的父类,调用父类的构造函数时

class Person:
    name =""
    age = 0
    def __init__(self,name,age):
        self.name = name
        self.age = age
class student:
    num = 0
    Class = 0
    def __init__(self,num,Class):
        self.num = num
        self.Class = Class
class CCC(Person,student):
    def __init__ (self,name,age,num,Class):
        Person.__init__(self,name,age)    #
        student.__init__(self,num,Class)  #
    def prt(self):
        print("%s %d %d %d\n" % (self.name,self.age,self.num,self.Class))
A = CCC("xiaoming",18,16031210113,1)
A.prt()

②、继承两个父类,且这两个父类的父类相同。这样多重继承就不是一棵树了

如:

class A(object):
    def __init__(self, a):
        print ('init A...')
        self.a = a

class B(A):
    def __init__(self, a):
        super(B, self).__init__(a)
        print ('init B...')

class C(A):
    def __init__(self, a):
        super(C, self).__init__(a)
        print ('init C...')

class D(B, C):
    def __init__(self, a):
        super(D, self).__init__(a)
        print ('init D...')
d = D('d')

结果:

继承关系:

像这样,同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次

3、python中获取对象信息

  ①、用 type() 函数获取变量的类型,它返回一个 Type 对象:

class student:
    name = ''
    sex = ''
    age = ''
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
print (type(123))
s = student("xiaoming","Male",18)
print (type(s))

结果:

2、用 dir() 函数获取变量的所有属性:

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

dir()返回的属性是字符串列表,如果已知一个属性名称,要获取或者设置对象的属性,就需要用 getattr()  setattr( )函数了

3、可变长参数和字典的遍历

① tupleArg前面“*”表示这个参数是一个元组参数,从程序的输出可以看出,默认值为();dicrtArg前面有“**”表示这个字典参数(键值对参数)。可以把tupleArg、dictArg看成两个默认参数。多余的非关键字参数,函数调用时被放在元组参数tupleArg中;多余的关键字参数,函数调用时被放字典参数dictArg中

# coding = utf-8
class Person(object):

    def __init__(self, name, gender, **kw):
        self.name = name
        self.gender = gender
        for k, v in kw.items():         # **kw接受多余的关键字参数(键值对),遍历字典
            setattr(self, k, v)        

p = Person('Bob', 'Male', age=18, course='Python')
print (p.age)
print (p.course)
print (filter(lambda x: x[0]!='_', dir(p)))      #过滤器,把类的实例p中属性,因用dir()函数,属性都是以字符串形式表式

② 遍历字典链接:点击

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值