一、对象的特有名称空间
# 对象独有的名称空间:在产生对象时就赋初值
'''
class ted:
def func(): 当func里不存在参数时,调用时不需要给值
print('hah')
ted.func()
'''
'''
class ted:
def func(self):
print('hah')
ted.func('useless')
'''
#类里面的方法属于谁的名称空间,就被谁调用
#类里面的方法的名称空间不属于对象,怎么实现调用这些方法
#方法如下:
#1
class student:
def set_stu(stu,name,sex):
stu.name=name
stu.sex=sex
stu1=student()
#将对象stu1作为参数传递到方法里去 此时将对象的名称空间里放入我们想要的值,也就是赋值
student.set_stu(stu1,'bob','male')
print(stu1.__dict__) #{'name': 'bob', 'sex': 'male'}
print(stu1.name) #bob
print(stu1.sex) #bob
#2
#将产生的对象的空的名称空间与名称空间赋值操作整合
class students:
#__init__会在实例化对象时被调用
#1.会为实例化的对象形成空的名称空间
#2.就是一个方法,可以被传参,在类名(实参)这种方式下调用并传参 __init__(self,形参)
#第一个self就是要产生的当前对象
#在方法内部,形参拿到了实参值,使用self.属性名=形参 本质上=实参,为对象的名称空间添加属性!
def __init__(self,name,sex):
print('1<<<',self)
self.name=name
self.sex=sex #建议新增的参数与属性名(变量名)命名保持一致
return None #默认值返回为None
stu2=students('tom','female')
print(stu2.name,stu2.sex) #tom female
二、类中方法的第一个默认参数:对象方法
class student:
pass
text=student()
def func():
print('我又来了!')
student.func=func #在类的字典中添加func这个key,value为对应的函数func的地址,即为类添加东西
# print(student.__dict__)
class student1:
pass
text1=student1()
def func1(a): #此处需要一个参数a,用来接受text1自身
print('你咋又来了?')
student1.func1=func1
text1.func1() #==student1.__dict__['func1](text1)
# 给类添加一个函数,通过对象去调用这个函数,本质上等价于在这个函数中传入一个参数text1
#对象使用类的函数,本质上还是通过类去获取对应的关系,将对象传进去
#总结:所有的函数的第一个参数都是通过类调用函数传进去来调用对象
text1.func1()==student1.__dict__['func1'](text1)==student1.func1(text1)
# 对象调用方法的第一个参数一定是调用该方法的参数!
三、类方法
#类方法
#下面所有为自己推导的,先自己了解一下相关流程,系统有更好的方法,在后面介绍
class tool:
#类自己的方法
def add(n1,n2):
return n1+n2
res=tool.add(10,20) #类使用自己的方法时,存在几个参数就传入几个
print(res) #30
text=tool()
#print(text.add(10,20)) 这样输出,会出错,原因是加上自身,我们给了3个实参,而方法只接受了2个参数
#接受的第一个参数是其本身(text),第二个是给的参数10,第三个未被接收
#小点:类的名字,对象都可以使用,但是出现了类与对象使用方法时,传入的参数有差异!
#解决的方案 语法糖
class took:
def acd(cls,n1,n2):
cls.fn()
return n1+n2
def fn(): #里面不给参数时,类调用时不需要给实参,对象调用时需要给定一个实参,可以为self,也可以为其它
print('小样,咋又来了?')
#如果方法a被对象took调用,那么也会在内部调用b, b间接被外界对象took调用
def a(self):
self.b()
def b(self):
pass
text1=took()
res=took.acd(took,10,20)
# print(text1.acd(10,20)) #此时会出错,在调用方法fn时,缺少自身的一个参数
#系统的方法 @classmethod 装饰器
class Tool:
#类方法:可以被类与对象调用的方法,第一个参数一定是类
#类方法不建议拿对象来调用
@classmethod
def add(cls,n1,n2):
print(id(cls)) #两个地址是一样的,还是证明了对象是通过类去调用方法的!因此不建议用对象此时来调用方法
return n1+n2
print(Tool.add(12000,18000)) #此时传入的第一个参数是类本身
tool=Tool()
print(tool.add(13,15)) #对象调用类方法,此时传入方法的第一个参数不是对象,而是 tool.__class__
·
四、属性与方法的总结
#属性与方法的总结(类最好使用类方法,对象最好使用对象方法)
class china:
#属于类的属性
name='wuchanghu'
#属于对象的属性
def __init__(self,name):
self.name=name
#属于类的方法,获取名字
@classmethod
def get_name(cls):
return cls.name
#属于对象的方法,获取名字
def get_names(self):
return self.name
city=china('anqing')
country=china('wangjiang') #产生两个对象
#类方法的使用
print(china.get_name()) #类调用自己的方法
print(city.get_name()) #对象来调用
print(country.get_name())
#总结:类方法拿对象调用并没有多少意义,不建议拿对象来调用
#对象方法的使用
print(china.get_names(city))
print(china.get_names(country)) #类来调用对象的方法
print(city.get_names())
print(country.get_names())#对象来调用对象方法,本质上还是通过类去调用
五、封装
class func:
def get_box(self):
print('找到保险箱')
def get_money(self):
print('取出12000')
fn=func()
fn.get_box()
fn.get_money() #在类外面可以取到里面的值
#需求:将类中的一些功能与属性进行隐藏,不让外界总结访问(可以间接访问)
#措施: 在属性前面加上__,此时在外界不能通过__属性取出
#下面是类的封装
class func:
__name='jun' #也可对类的属性进行隐藏
@classmethod
def __get_box(cls):
print('输入密码,找到保险箱')
cls.__get_money() #在内部可以通过__get_box()来访问另外的属性
@classmethod
def __get_money(cls):
#可以在此添加具体数据与功能来做安全操作
print('取出12000')
fn=func()
fn._func__get_box() #输入密码,找到保险箱 取出12000
print(fn._func__name)
#虽然说此时进行了封装,然而对熟知python规则的人来说,真的是一个鸡肋
#下面是类的属性的封装
class f1:
def __init__(self,money):
self.__money=money
def __text(self):
print('run away')
a=f1(8888) #值可以正常传入
a._f1__text()
print(a._f1__money) #取出需要通过_f1__money来做到
#下面是对象的属性的获取
class dx:
def __init__(self):
print('hah')
self.money=200
# return self.money return 的返回值应该为None
def fun1(self,money):
self.money=money
return self.money
d=dx()
print(d.money) #200
print(d.fun1(100)) #100
print(d.money) #100 self.money对于对象自己来说就是一个变量而已,只是在用他的变量名,值可以改变
#对象的封装
#对象方法的封装
class dx:
def __init__(self):
print('hah')
self.__money=200
def __fun1(self,money):
self.money=money
return self.money
x=dx()
print(x._dx__money) #200
print(x._dx__fun1(333)) #300
print(x._dx__money) #200 因为fun1里面的money与__money不是同一个变量
#对象属性的封装
class dx:
def __init__(self):
print('hah')
self.__money=200
def __fun1(self,money):
self.__money=money
return self.__money
x=dx()
# print(x.money) #此时通过这种途径找不到
print(x._dx__money) #200
print(x._dx__fun1(333)) #333
print(x._dx__money) #333 同一个变量名,值一改变,就都变了
封装的另外一种取值方法:
对象的属性:封装的目的
1.对象的属性值一般来源于外界,外界是有权利再次访问的
2.封装的目的不是让外界无法访问,而是不让其直接访问,可以在完成安全处理后再访问
class dx:
def __init__(self):
print('haha')
self.__money=200
@property #取值 #加上@property a.money代表使用该方法,而不再是找这个money函数的函数名
def money(self):
print('走方法拿到的money') #走方法拿到的money 200
return self.__money
# #赋值
@money.setter #加上了@money.setter,实际上是调用了该方法,并给其传值 a.money=1111 == a.money(1111)
def money(self,money):
self.__money=money
print('我有没有走')
return self.__money
#删除
@money.deleter #加上这个装饰器,外界的删除,会调用该方法,在其内部在做相应处理
def money(self):
print('逗你玩')
# del self.__money #在类内部可以访问到其他方法,注释该功能后,系统并没有删除掉该属性
a=dx()
print(a.money) #走方法拿到的money 返回self.__money=200
a.money=111 #我有没有走 返回赋值后的money=111
print(a.money) #走方法拿到的money 返回已经赋值后的self.__money=111
del a.money #在类外面,此时的del a.money 并不是直接删除,而是通过调用 删除方法 完成相对应的功能
print(a.money) #走方法拿到的money 属性money并没有删除
#总结:约定俗成,对一种属性提高对外的接口时,也就是加上了这几个装饰器,那这些属性对应的方法名必须是一样的!
# 同时,@property必须在上面,其他随意,因此存在一定的顺序