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')
结果:
继承关系:
像这样,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()函数,属性都是以字符串形式表式
② 遍历字典链接:点击