前言
终于又开始了分享,歇歇停停可算是把python面向对象这块的东西学完了,在开学之际来做个总结。确实,假期的效率是低的惊人,希望疫情结束,开学不要推迟的太久,早早相见!!!
类:具有相似功能和特性的一类事物
类 一个公共模板,对象是从这个公共模板产出的
对象:类的具体体现
Student 类名具有描述性,类名首字母大写,类名不宜用_
属性(变量名) 方法(函数)
从类名的角度分析类
查看类中的所有的内容
print(Student.__dict__) 只用于获取类中的所有内容 运行结果: {'__module__': '__main__', 'daily': '学习', 'examination': '考试', 'work': <function Student.work at 0x000001D580B7D0D0>, 'homework': <function Student.homework at 0x000001D580B7D160>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
万能的 .
1、查看 print(Student.daily) 运行结果: 学习 2、增加 Student.cloth = '校服' print(Student.__dict__) 运行结果: {'__module__': '__main__', 'daily': '学习', 'examination': '考试', 'work': <function Student.work at 0x000002D7DC06D0D0>, 'homework': <function Student.homework at 0x000002D7DC06D160>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'cloth': '校服'} 3、修改 Student.examination = '不考试' print(Student.examination) 运行结果: 不考试 4、删除 del Student.daily print(Student.__dict__) 运行结果: {'__module__': '__main__', 'examination': '不考试', 'work': <function Student.work at 0x0000014E956BD0D0>, 'homework': <function Student.homework at 0x0000014E956BD160>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'cloth': '校服'}
一般类中的属性都是通过类名.的方式去操控的
一般类中的方法(除去类方法、静态方法外)不通过类名调用
从对象的角度分析类
对象
类名() 就是实例化一个对象的过程
发生了三件事
- 1、自动执行object类中的__new__方法,在内存中创建一个对象空间
- 2、自动执行__init__方法,并且将对象空间传给self参数
- 3、执行__init__方法里面的代码,给对象空间封装其属性
class Student:
daily = '学习'
examination = '考试'
def __init__(self):
print(self)
print('666')
obj = Student()
print(obj)
运行结果:
<__main__.Student object at 0x0000016297271E50>
666
<__main__.Student object at 0x0000016297271E50>
#obj传给self
#实例化对象 自动执行__init__方法
对象操作对象里面的属性
对象查看全部属性
obj = Student() print(obj.__dict__) 运行结果: {'n': 'ly', 'sex': 'male'}
对象操作对象空间的属性
obj.age = '20' #增 del obj.age #删 obj.n = 'yl' #改 print(obj.n) #查 与从类名角度分析类似
一个类可以有多个对象
class Student: daily = '学习' examination = '考试' def __init__(self, n, a, s): self.name = n self.age = a self.sex = s def work(self, c): self.color = c print(f'{self.name}的家庭作业') liye = Student('liye', 20, 'male') xll = Student('xll', 19, 'female') print(liye.__dict__) print(xll.__dict__) 运行结果: {'name': 'liye', 'age': 20, 'sex': 'male'} {'name': 'xll', 'age': 19, 'sex': 'female'}
对象查看类中的属性
万能的 .
print(liye.daily)
运行结果:
学习
对象只能查看类中的属性,不能修改
eg:
liye.daily = '唱歌'
此时是对对象中的属性的增加
print(liye.__dict__)
{'name': 'liye', 'age': 20, 'sex': 'male', 'daily': '唱歌'}
对象调用类中的方法
liye = Student('liye', 20, 'male')
liye.work('蓝色')
Print(liye.__dict__)
运行结果:
liye的家庭作业
{'name': 'liye', 'age': 20, 'sex': 'male', 'color': '蓝色'}
self 就是类中方法的第一个位置参数,如果通过对象执行此方法,解释器就自动的将此对象空间当作实参传给self
约定俗称:类中的方法第一个参数一般都设置为self
从空间角度研究类
添加类的对象属性
类的外部
class A: address = '中国' def __init__(self, name): self.name = name obj = A('ly') respose = input('yes or no') if respose == 'yes': obj.age = 20 print(obj.__dict__) #{'name': 'ly', 'age': 20}
类的内部
class B: address = '陕西' def __init__(self,name): self.name = name def age(self): if self.name == 'ly': self.age = 20 obj1 = B('ly') obj1.age() print(obj1.__dict__) #{'name': 'ly', 'age': 20}
添加类的静态属性
类的外部
A.tempar = '39' print(A.__dict__) # {'__module__': '__main__', 'address': '中国', '__init__': <function A.__init__ at 0x000002B5126BD0D0>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None, 'tempar': '39'}
类的内部
class C: address = '西安' def __init__(self, name): self.name = name def add(self): C.tempar = '38.6' obj2 = C('ly') print(obj2.__dict__) #{'name': 'ly'} # obj2.add() # C.add(111) C.add(obj2) print(obj2.__dict__) #{'name': 'ly'} print(C.__dict__) #{'__module__': '__main__', 'address': '西安', '__init__': <function C.__init__ at 0x000002BD6A91D280>, 'add': <function C.add at 0x000002BD6A91D310>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None, 'tempar': '38.6'}
对象查找类的属性规则
- 对象查找属性的顺序:先从对象空间找 --------> 类空间找 -------> 父类空间找 ------->…
- 类名查找属性的顺序:先从本类空间找 --------> 父类空间找-------->…
- 单项不可逆,类名不可能找到对象的属性,且对象不可能修改类的静态属性
在未添加ly的mind时,若del ly.mind 报错:对象只能查看类中的属性,不可修改,在此也是查找属性的位置
对象与对象之间原则上相互独立(除去组合这种特殊关系之外)
类与类之间的关系
依赖关系(主从关系)
将一个类的类名或者对象传给另一个类的方法中
eg:在棒球运动中,有击球手,有接球手,当击球动作产生时紧接着便是接球动作的执行。比如两个类击球手类和接球手类,击球手的击球方法执行后立马执行接球手的接球方法,此动作的实现便应用了依赖关系,将接球手的对象传给击球手类的击球方法:
class Bater:
def __init__(self, name):
self.name = name
def bat(self, obj):
print(f'{self.name}击球了')
obj.catch()
class Catcher:
def __init__(self, name):
self.name = name
def catch(self):
print(f'{self.name}接到了')
obj1 = Bater('ly')
obj2 = Catcher('yl')
obj1.bat(obj2)
运行结果:
ly击球了
yl接到了
组合关系(关联组合聚合)
将一个类的对象封装成另一个类的对象的属性
eg:以相亲为例,男女朋友的交互性,就需要拿男生的类来封装女生类的属性,以此来有联系,达到谁的男朋友是谁
class Boy:
def __init__(self, name):
self.name = name
def meet(self,girl_friend = None):
self.girl_friend = girl_friend
def have_dinner(self):
if self.girl_friend:
print(f'{self.name}请{self.girl_friend.age}岁大的{self.girl_friend.name}吃饭') self.girl_friend.go_shopping(self)
else:
print('努力找女朋友吧')
class Girl:
def __init__(self, name, age):
self.name = name
self.age = age
def go_shopping(self, boy_friend):
print(f'{self.name}和{boy_friend.name}一起去购物')
ly = Boy('李烨')
jt = Girl('景甜', 20)
ly.meet(jt)
ly.have_dinner()
运行结果:
李烨请20岁大的景甜吃饭
景甜和李烨一起去购物
继承关系
面向对象的三大特性:封装、继承、多态
什么是继承:
- 专业角度:B继承A类,B就叫做A的子类,派生类,A就叫做B的父类,基类,超类。B类以及B类的对象使用A类的所有的属性和方法
- 单继承,多继承
继承的优点:
- 节省代码
- 增强耦合性
- 代码规范化
- 重写父类代码
单继承
子类以及对象可以调用父类的属性方法
class Animal: live = '有生命的' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex def eat(self): print(f'p1--->{self}') print('动物都需要进食') class Person(Animal): pass class Dog(Animal): def eat(self): print('狗狗也要生活') #从类名执行父类的属性 print(Person.__dict__) print(Person.live) #有生命的 #从对象执行父类的一切 #实例化对象一定会执行三件事,__init__ p1 = Person('ly', 20, 'male') print(p1.live) #有生命的 p1.eat() print(f'p1--->{p1}') ''' p1---><__main__.Person object at 0x00000250AAA33BB0> 动物都需要进食 p1---><__main__.Person object at 0x00000250AAA33BB0> ''' Dog.live = '狗生' print(Dog.live) #狗生 print(Animal.live) #有生命的 #注意:子类以及子类对象只能调用父类的属性以及方法,不能操作(增删改) p2 = Dog('merry', 3, 'female') p2.eat() #子类将父类的方法覆盖 #狗狗也要生活
对象查找顺序 从对象空间找 -----> 子类找 -----> 父类找
既要执行父类方法又要执行子类方法:
法一:
class Plant: def __init__(self, name, age): self.name = name self.age = age class Shuixian(Plant): def __init__(self, name, age, yezi): Plant.__init__(self, name, age) self.yezi = yezi obj = Shuixian('puple', 3, '双叶') print(obj.__dict__) #{'name': 'puple', 'age': 3, 'yezi': '双叶'}
法二:super
class Plant: def __init__(self, name, age): self.name = name self.age = age class Shuixian(Plant): def __init__(self, name, age, yezi): # super(Shuixian, self).__init__(name, age) super().__init__(name, age) self.yezi = yezi obj = Shuixian('puple', 3, '双叶') print(obj.__dict__) #{'name': 'puple', 'age': 3, 'yezi': '双叶'}
多继承
面向对象:
python2.2之前:都是经典类
python2.2直至python2.7之间存在两种类型:经典类,新式类
- 经典类:基类不继承object,查询规则 依靠深度优先的原则
- 新式类:基类必须继承object,查询规则 mro算法
python3x:只有新式类
class Animal: def work(self): print('动物会吃饭') class People: def language(self): print('人类可以说话') class Mermaid(Animal,People): pass merry = Mermaid() merry.work() merry.language() #动物会吃饭 #人类可以说话
如上:美人鱼既满足人的方法也满足动物的方法,通过多继承,使子类对象可以调用两个父类的动作
但当父类有相同的方法时,继承哪个成为了一个问题 ------ 继承顺序
深度优先:一条路走到黑
mro算法:
MRO是一个有序列表L,在类被创建时就计算出来。 计算公式:
mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )(其中Child继承自Base1, Base2)
对[Base1, Base2]的操作为Merge操作,其中:
表头: 列表的第一个元素
表尾: 列表中表头以外的元素集合(可以为空)
列表:[A, B, C]
表头是A,表尾是[B, C]Merge操作示例:
如计算merge( [E,O], [C,E,F,O], [C] ) 有三个列表 : ① ② ③ 1 merge不为空,取出第一个列表列表①的表头E,进行判断 各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表 2 取出列表②的表头C,进行判断 C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除 merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] ) 3 进行下一次新的merge操作 ...... ---------------------
eg:
mro(A) = mro(A(B,C)) = [A] + merge(mro(B), mro(C), [B,C])
mro(B) = mro(B(D,E)) = [B] + merge(mro(D), mro(E), [D,E])
= [B] + merge([D,O], [E,O],[D,E] 单继承:mro(D) = [D,O]
= [B,D] + merge([O],[E,O],[E])
= [B,D,E] + merge([O],[O])
= [B,D,E,O]
mro(C) = mro(C(E,F)) = [C] + merge(mro(E) , mro(F), [E,F])
= [C] + merge([E,O], [F,O], [E,F])
= [C,E] + merge([O],[F,O],[F])
= [C,E,F] + merge([O],[O])
= [C,E,F,O]
mro(A) = [A] + merge([B,D,E,O], [C,E,F,O], [B,C])
= [A,B] + merge([D,E,O], [C,E,F,O], [C])
= [A,B,D] + merge([E,O], [C,E,F,O], [C])
= [A,B,D,C] + merge([E,O], [E,F,O])
= [A,B,D,C,E] + merge([O], [F,0])
= [A,B,D,C,E,F] + merge([O], [O])
= [A,B,D,C,E,F,O]
print(A.mro()) 可直接查看mro排序顺序
面向对象的三大特性
继承
super的深入了解
super() 严格意义上并不是执行父类的方法
- 单继承: super()执行父类的方法
- 多继承:super(S,self) 严格按照self从属于的类的mro的执行顺序,执行 S类的下一位
class A: def f1(self): print('in A') #首先输出 1 class Foo(A): def f1(self): super(Foo, self).f1() #Foo 的下一类 Bar print('in Foo') # 3 class Bar(A): def f1(self): super(Bar, self).f1() #Bar 的下一类 A print('in bar') # 2 class Info(Foo,Bar): def f1(self): super(Info, self).f1() # Info 的下一类 Foo print('in Info') # 4 obj = Info() print(Info.mro())# [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>] obj.f1() 运行结果: ''' in A in bar in Foo in Info '''
封装
将一些东西内容封装到一个地方,还可以取出
类设置静态属性,设置一些方法…
eg:name,age被封装,以.的方式取出
class Person:
class_name = '20060317'
def __init__(self,name,age):
self.name = name
self.age = age
ly = Person('刘烨', 20)
print(ly.age)
print(ly.name)
多态
一个事物有多种形态,python中默认支持多态
eg:弱类型语言python 与 强类型语言对变量的定义
python:
name = 111 name ='dwaf' name = [1, 2, 3]
c语言:
string name = 'ly' int age = 2
鸭子类型:你看起来像鸭子,那么你就是鸭子
class A:
def f1(self):
print('in A f1')
def f2(self):
print('in A f2')
class B:
def f1(self):
print('in A f1')
def f2(self):
print('in A f2')
如上:A 和 B两个类完全没有耦合性,但是在某种意义上他们却统一了一个标准。
对相同的功能设定了相同的名字,这样方便开发,这两个方法就可以互成为鸭子类型。
鸭子类型的应用:
例如不同数据类型list, tuple等的find, index 方法,两个类型没有耦合性,但对相同的功能设定了相同的名字,达到相同功能使用方便
定义类似如下:
class List:
def find(self):
pass
def index(self):
pass
class Tuple:
def find(self):
pass
def index(self):
pass
应用示例:
lis = [1, 2, 3]
print(lis.index(2)) #1
tu = (1, 2, 3)
print(tu.index(2)) #1
类的约束
类的约束的两种解决方法:
在父类建立一种约束
在父类定义一个pay方法,主动抛出异常,如果子类没有定义pay方法,并且沿用了父类的pay方法,就会报错
python推荐的一种约束方式
class Payment:
def pay(self, money):
raise Exception('子类必须定义此方法')
class QQpay(Payment):
def pay(self, money):
print(f'利用QQ支付了{money}')
class Alipay(Payment):
def pay(self, money):
print(f'利用支付宝支付了{money}')
class Wechat(Payment):
# def pay(self, money):
def fuqian(self, money):
print(f'利用微信支付了{money}')
def pay(object, money):
object.pay(money)
obj = Wechat()
pay(obj, 100)
'''
运行结果:
Exception: 子类必须定义此方法
'''
模拟抽象类(指定一种规范)的概念,建立一种约束
固定方法:
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
# 抽象类 接口类 规范和约束 metaclass指定的是一个元类
@abstractmethod
def pay(self):pass # 抽象方法
基类如上设置,子类如果没有定义pay方法,在实例化对象时就会报错
eg:
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self, money):
pass
class QQpay(Payment):
def pay(self, money):
print(f'利用QQ支付了{money}')
class Alipay(Payment):
def pay(self, money):
print(f'利用支付宝支付了{money}')
class Wechat(Payment):
def fuqian(self, money):
print(f'利用微信支付了{money}')
def pay(object, money):
object.pay(money)
obj = Wechat()
'''
TypeError: Can't instantiate abstract class Wechat with abstract method pay
'''
类的成员
细分
class A:
company_name = '华为' # 静态变量(静态字段)
__iphone = '0913xxxx' # 私有静态变量(私有静态字段) 带双下划线
def __init__(self,name,age): #特殊方法
self.name = name #对象属性(普通字段)
self.__age = age # 私有对象属性(私有普通字段)
def func1(self): # 普通方法
pass
def __func(self): #私有方法
print(666)
@classmethod # 类方法
def class_func(cls):
""" 定义类方法,至少有一个cls参数 """
print('类方法')
@staticmethod #静态方法
def static_func():
""" 定义静态方法 ,无默认参数"""
print('静态方法')
@property # 属性
def prop(self):
pass
类的私有成员
只能在类的内部调用
私有成员来说:当你遇到重要的数据,功能,(只允许本类使用的一些方法,数据)设置成私有成员
私有类的静态属性
# 在类的内部可以访问 class A: name = 'ly' __name = 'yll' def func(self): print(self.name) print(self.__name) obj = A() obj.func() ''' ly yll ''' # 类的外部不能访问 print(obj.name) # ly ''' print(obj.__name) 'A' object has no attribute '__name' ''' # 类的派生类不能访问 class B(A): pass objx = B() ''' print(B.__name) type object 'B' has no attribute '__name' '''
私有类的方法
class A: def __func(self): print('in A __func') def func(self): self.__func() print('in A func') objf = A() objf.func() ''' in A __func in A func ''' ''' objf.__func() 'A' object has no attribute '__func' '''
私有对象的属性
class A: def __init__(self, name, pwd): self.name = name self.__pwd = pwd def change_pwd(self): self.__pwd = '123' objd = A('ly', '12431') objd.change_pwd() ''' print(objd.__pwd) 'A' object has no attribute '__pwd' '''
python所有的私有成员都是"纸老虎",形同虚设
类从加载中,只要遇到类中的私有成员,都会在私有成员前面加上 _类名
class B:
name = 'liu'
__name = 'liuy'
def __func(self):
print('111')
print(B.__dict__)
obj = B()
print(obj._B__name)
obj._B__func()
'''
liuy
111
'''
类方法
一般就是通过类名去调用的方法, 并且自动将类名地址传递给cls,
但是如果通过对象调用也可以,传的地址仍然是类名地址
class C:
def func(self):
print('实例方法')
@classmethod
def cls_func(cls):
print(f'cls -> {cls}')
print('类方法')
print(C)
C.cls_func()
'''
<class '__main__.C'>
cls -> <class '__main__.C'>
类方法
'''
obj = C()
obj.cls_func()
'''
cls -> <class '__main__.C'>
类方法
'''
对于面向对象的编程,类方法的作用表现在:
- 得到类名可以实例化对象
- 可以操作类的属性
eg:
#创建学生类,只要实例化一个对象,写一个类方法,统计一下具体实例化对象的个数
class Student:
count = 0
def __init__(self, name, age):
self.name = name
self.age = age
self.total()
@classmethod
def total(cls):
cls.count = cls.count + 1
@classmethod
def num(cls):
return cls.count
p1 = Student('ly', 20)
p2 = Student('ly', 20)
p3 = Student('ly', 20)
p4 = Student('ly', 20)
p5 = Student('ly', 20)
print(Student.num())
# 5
静态方法
不依赖于对象与类,其实静态方法就是函数
但依靠类名,对象调用
class D:
def func(self):
print('实例方法')
@staticmethod
def static_func():
print('静态方法')
D.static_func()
c = D()
c.static_func()
'''
静态方法
静态方法
'''
类似于:
def static_func():
print('静态方法')
static_func()
保证代码的规范性,合理划分,以及后续的维护性
eg:静态方法不依赖于对象与类,但属于时间大类的功能,合理划分
class Time:
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
def change_time(self):
print(f'你修改的时间为{self.hour}:{self.minute}:{self.second}')
@staticmethod
def now_time():
import time
print(time.strftime('%H:%M:%S'))
x = Time('11', '5', '21')
x.change_time()
x.now_time()
属性
property 将执行一个函数需要函数名() 变换为直接函数名
将动态方法伪装成一个属性,虽然在代码级别上没有什么提升,但是让你看起来更合理
eg:BMI系数对于人们来说应该是属性一样的东西,并非一种方法,通过@property将方法伪装成属性
class Person: def __init__(self, name, weigth, height): self.name = name self.weight = weight self.height = height @property def bim(self): return self.weight / self.height ** 2 ly = Person('ly', 70, 1.72) print(ly.bim)
property是一个组合
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
设置属性的两种方式
1、利用装饰器
class Foo: @property def ABC(self): print('get的时候运行我') @ABC.setter def ABC(self, value): print(value) print('set的时候运行我') @ABC.deleter def ABC(self): print('delete的时候运行我') obj = Foo() obj.ABC # get的时候运行我 obj.ABC = 666 ''' 666 set的时候运行我 ''' del obj.ABC # delete的时候运行我
2、利用实例化对象的方式
class Foo: def get_AAA(self): print('get的时候运行我') def set_AAA(self,value): print('set的时候运行我') def delete_AAA(self): print('delete的时候运行我') AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应 f1=Foo() f1.AAA # get的时候运行我 f1.AAA = 'aaa' # set的时候运行我 del f1.AAA # delete的时候运行我
应用场景:一些方法名类似于属性,可以让其伪装为属性
isinstance issubclass
- isinstance 判断的是对象与类的关系 isinstance(a,b) a是否是b类或者b类派生类实例化的对象
class A:
pass
class B(A):
pass
obj = B()
print(isinstance(obj, A))
print(isinstance(obj, B))
'''
True
True
'''
- issubclass 判断的是类与类之间的关系 issubclass(a,b) a类是否是b类 子孙类
class A:
pass
class B(A):
pass
class C(B):
pass
print(issubclass(B, A))
print(issubclass(C, A))
'''
True
True
'''
type元类
type不仅可以查看数据的类型,也可以获取对象所从属于的类
print(type("dwafaf")) print(type(list)) print(type(tuple)) print(type(str)) ''' <class 'str'> <class 'type'> <class 'type'> <class 'type'> '''
python中一切皆对象,类在某种意义上也是一个对象,python中自己定义的类以及大部分内置类,都是由type元类(构建类)实例化得来的
type与object的关系
object类是type类的一个实例
print(type(object)) # <class 'type'>
object类是type类的父类
print(issubclass(type, object)) # True
反射
程序对自己内部的一种自省方式
反射:通过字符串操作对象的方式
应用于:
实例对象
类
本模块
其他模块
hasattr getattr setattr delattr
实例对象
class Person:
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('in Person func')
obj = Person('ly', 20)
hasattr:检测是否含有某属性
print(hasattr(obj, 'name')) print(hasattr(obj, 'age')) print(hasattr(obj, 'country')) ''' True True True '''
getattr:获取属性
print(getattr(obj, 'name')) f = getattr(obj, 'func') f() ''' ly in Person func ''' 当属性不存在时,可添加参数设置返回值,不让报错 print(getattr(obj, 'sex', None)) # None 一般组合使用 if hasattr(obj, 'name') getattr(obj, 'name')
setattr:设置属性
setattr(obj, 'sex', '男') print(obj.sex) # 男
delattr:删除属性
delattr(obj, 'sex') print(obj.sex) # 'Person' object has no attribute 'sex'
类的角度
class Person:
country = 'China'
def __init__(self, name, age):
self.name = name
self.age = age
def func(self):
print('in Person func')
hasattr与getattr
if hasattr(Person, 'func'): obj = Person('ly', 20) getattr(Person, 'func')(obj) # in Person func
从本模块
import sys
sys.modules[__name__] 为本模块
a = 666
def func():
print('in 本模块')
import sys
print(getattr(sys.modules[__name__], 'a'))
if hasattr(sys.modules[__name__], 'func'):
getattr(sys.modules[__name__], 'func')()
‘''
666
in 本模块
'''
从其他模块
模块xll内容
name = 'ly' def func(): print('in xll') class C: def __init__(self, name, age): self.name = name self.age =age
执行文件
import xll print(getattr(xll, 'name')) if hasattr(xll, 'func'): getattr(xll, 'func')() ''' ly in xll '''
函数与方法的区别
通过打印函数名的方法区别
def func1():
pass
class A:
def func(self):
pass
# 1、通过打印函数名的方法区别什么是方法,什么是函数
print(func1)
print(A.func) #通过类名调用的类中的实例方法叫做函数
'''
<function func1 at 0x00000245A5F7D040>
<function A.func at 0x00000245A5F7D160>
'''
obj = A()
print(obj.func) # 通过对象调用的类中的实例方法叫方法
# <bound method A.func of <__main__.A object at 0x00000245A5CC97C0>>
借助模块判断
from types import FunctionType
from types import MethodType
def func():
pass
class A:
def func(self):
pass
objx = A()
print(isinstance(func, FunctionType))
print(isinstance(A.func, FunctionType))
print(isinstance(obj.func, FunctionType))
print(isinstance(obj.func, MethodType))
'''
True
True
False
True
'''
总结:函数都是显性传参,方法都是隐性传参
python中一切皆方法,类在某种意义上也是一个对象,python中自己定义的类,以及大部分内置类,都是由type元类(构建类)实例化得来的
python中一切皆对象,函数在某种意义上也是一个对象,函数这个对象是从FunctionType这个类实例化得来的
python中一切皆对象,方法在某种意义上也是一个对象,方法这个对象是从MethodType这个类实例化得来的
其它语言中:java中只有方法 c中只有函数 c++ 类中:方法 类外:函数
双下方法
双下方法的内容确实也是比较多的,我们就放在下一篇内容分享吧,开学快乐!!!