无论是风里,还是在雨里,我都在这里守候着你~
对于封装更正
私有方法,和私有属性,静态私有属性
class Person:
__person = '人类'
def __init__(self,name,age):
self.name = name
self.__age = age
def get_age(self):
return self.__age
def set_age(self,newage):
if newage>15:
self.__age = newage
else:
print('年龄需要大于15')
zhangsan = Person('张三',18)
# print(zhangsan.__age) #这样是调用不到这个属性的
print(zhangsan.get_age()) # 这样才是正确的调用方式
__person表示静态私有属性,在外部同样获取不到。在属性前加上__表示封装变成私有属性,在外部是不能调用的。只能在内部使用,我们再在Person中添加一个方法,用这个方法获取就可以了。
set_age:我们如果想要修改,如果想要对age有一个约束条件就可以这样写。
同样,我们在Person中的方法名加上一个__,就变成了私有方法,外部无法调用。在子类中也无法去调用。
将调用方法看上去像调用一个属性
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
p = Person('张三')
print(p.get_name)
@property:内置装饰器,实现如上效果。
但是get_name不能去传参数,如果我想要去修改呢?
如下:
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
@get_name.setter
def get_name(self,newname):
self.__name = newname
p = Person('张三')
print(p.get_name)
p.get_name = '李四'
print(p.get_name)
把get_name 当成属性去修改它即可。
删除一个属性:
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
p = Person('张三')
print(p.get_name)
del p.get_name
会被错,会提示can't delete attribute,不能删除。
那怎么样才能删除呢:
class Person:
def __init__(self,name):
self.__name = name
@property
def get_name(self):
return self.__name
@get_name.deleter
def get_name(self):
print('删除我')
p = Person('张三')
print(p.get_name)
del p.get_name
print(p.get_name)
执行会输出:
张三
删除我
张三
显然,没有报错,但是却没有删除,但是其中执行了删除我这个方法,也就是说我们在外面del一个属性(方法)实际上是调用了这个方法,那么我们将输出删除我这个方法修改成:
@get_name.deleter
def get_name(self):
del self.__name
即可。 第二次输出会报错:没有这个属性。
其他:
1、判断一个类是不是另一个类的子类:
class A:
pass
class B(A):
pass
print(issubclass(B,A)) # True
是返回True,不是返回False
2、判断一个对象是否是一个类的对象
class A:pass
a = A()
print(isinstance(a,A)) # True
是返回True ,不是返回False
定义类的规范
当我们想要定义一个类的规范的时候,比如支付宝和卫星都有支付功能,我想写一个方法,可以调用支付宝和微信的支付功能。
class Wechat:
def pay(self,money):
print('微信支付了%s元'%money)
class Alipay:
def pay(self,money):
print('阿里支付了%s元'%money)
def payzhifu(pay_nei,money):
pay_nei.pay(money)
wechat = Wechat()
p = payzhifu(wechat,100)
输出:微信支付了100元
看来是没有毛病的,但是如果再来一个百度支付,而百度的支付方法不是pay,那样就会报错,
所以我们需要写一个类的规范。让支付类都必须有pay方法。
这样:
from abc import abstractmethod,ABCMeta
class PayAncestors(metaclass = ABCMeta):
@abstractmethod
def pay(self,money):
pass
class Wechat(PayAncestors):
def pay(self,money):
print('微信支付了%s元'%money)
class Alipay(PayAncestors):
def pay(self,money):
print('阿里支付了%s元'%money)
def payzhifu(pay_nei,money):
pay_nei.pay(money)
wechat = Wechat()
p = payzhifu(wechat,100)
metaclass:指定元类
@abstractmethod:给他一个装饰器,表示要写一个类的规范了。
这样就定义了一个规范,他的子类都必须有pay方法,如果没有,就会报错,并提醒没有pay方法。
报错提示:Can't instantiate abstract class Wechat with abstract methods pay
我们称它为接口类。(在python中实际是没有接口类一说,在别的语言中有,python也可以实现,但是在python里没有接口类一说。只是模拟了接口类)他也可以叫做抽象类。(在python类中有抽象类,实实在在存在)
接口隔离原则:我们在定义以一个规范的时候,不要使用单一的总接口,也就是说,一个类中不要有多个方法,单一点。
总结:无论是抽象类还是接口类,都是面向对象的开发规范,并且都不能实例化,一般都是单继承,由于java中没有多继承,所以接口类是从java中引来的,java利用创捷接口来规范多继承。python中不存在接口类一说,只是在python中模拟了一下写法,但是在python中有抽象类,写法和上面是一样的。
类方法
class Person:
__person = '人类'
def __init__(self,name):
self.name = name
def get_person(self,newperson):
Person.__person = newperson
return Person.__person
zhangsan = Person('张三')
print(zhangsan.get_person('动物类'))
如上我们可以发现,当把静态属性改为私有,修改的时候我们大概会这样写,每次都需要需要Person.xxx来调用和修改,这样就出来了一个类方法,也就是将self替换成自己这个类对象。于是修改成:
class Person:
__person = '人类'
def __init__(self,name):
self.name = name
@classmethod
def get_person(cls,newperson):
cls.__person = newperson
return Person.__person
zhangsan = Person('张三')
print(zhangsan.get_person('动物类'))
@classmethod:加一个装饰器表示类方法,不需要去实例化了。
cls:代表这个类本身。
当我们只修改,只需要静态属性的时候我们就需要这样做。
静态方法
当我们类中的方法没有用到类中的参数时候,我们可以不需要实例化类,来直接调用。
实例:
class Person:
def __init__(self,name,age)
self.name =name
self.age = age
@staticmethod
def getwrite():
name = input('name:')
age = input('age:')
Person(name,age)
在以前,我们调用需要先这样:
p = Person('张三'.18)
但是现在我们用@staticmethod声明他是一个静态方法之后,我们只需要这样:
Person.getwrite()即可。
让我们没有用到类中的任何参数,就可以这样定义。
反射
以字符串的形式去获取变量并操作。和eval相似,但是比eval强大。
class Person:
list = ['星期一','星期二','星期三','星期四']
def fun_one(self):
print('我是第一个方法')
def fun_two(self):
print('我是第二个方法')
如果我们想要拿到list列表,可以这样:
li = getattr(Person,'list')
输出:['星期一', '星期二', '星期三', '星期四']
直接输出一个列表。假如在Person中没有这个list那不就会报错了?是的
所以:
if hasattr(Person,'list'):
li = getattr(Person,'list')
hasattr():如果存在会返回True,否则返回False。二者搭配使用即可。
如果想要调用方法:同样的使用方式,但是获取到的只是一个内存地址,需要加上括号后执行
class Person:
list = ['星期一','星期二','星期三','星期四']
def fun_one(self):
print('我是第一个方法')
def fun_two(self):
print('我是第二个方法')
p = Person()
func = getattr(p,'fun_one')
func()
反射模块属性
getattr(模块名,'属性名')
反射模块方法
ret = getattr(模块名,'方法名')
ret()
总结:什么是可以反射的?
凡是xxx.qqq格式能获取到的的都可以,xxx写在getattr()方法的第一个参数,qqq写在getattr()的第二个参数。
反射当前页面的值:
import sys
name = '张三'
print(getattr(sys.modules[__name__],'name'))即可。
方法也就大同小异了。
反射修改
class A:
pass
a = A()
setattr(a,'name','张三')
反射删除变量
class A:
name = 'lisi'
delattr(A,name)