赞
踩
class Dog: type = '狗' def __init__(self): name = None @staticmethod def introduce(): # 静态方法不会自动传递实例对象和类对象 print('犬科哺乳类动物,属于肉食目') dog = Dog() Dog.introduce() dog.introduce() #输出 犬科哺乳类动物,属于肉食目 犬科哺乳类动物,属于肉食目
静态方法是类中的函数,不需要实例
静态方法主要是用来存放逻辑性的代码,逻辑上属于类,但和类本身没有关系。在静态方法中,不会涉及类中属性和方法的操作。
可以理解为静态方法是一个独立单纯的函数,仅仅是托管与某个类的名称空间中,便于维护和管理。
class Dog:
__type = '狗'
# 类方法,用class来进行装饰
@classmethod
def get_type(cls):
return cls.__type
print(Dog.get_type())
#输出
狗
注意:类中定义同名的方法,会优先调用最后一个定义的。
class Dog: def demo_method(self): print('对象方法。') @classmethod def demo_method(cls): print('类方法。') @staticmethod def demo_method(): #最后被定义,调用时优先进行 print('静态方法。') dog = Dog() Dog.demo_method() dog.demo_method() #输出 静态方法。 静态方法。
如果我们现在需要设计一个银行账户类,这个类中包含账户人姓名和余额。(假如不考虑接口操作)
class Bank:
def __init__(self, name, money):
self.name = name
self.money = money
问题:
不安全(设计简单,所有属性可以被外部访问修改,非常不安全)
金额不允许直接让用户修改,如果修改只能去窗口办理。
在使用对象时,尽量不要让使用者直接操作对象中的属性,因为直接操作会带来安全隐患。
这个时候考虑私有属性
class Bank:
def __init__(self, name, money):
self.__name = name
self.__money = money
代码改进以后,将所有的属性设计成私有属性。确实从外部使用时,不知道内部的属性,不能直接修改对象,隐藏了实现的细节。
添加方法,访问私有属性。
class Bank:
def __init__(self, name, money):
self.__name = name
self.__money = money
def get_name(self):
return self.__name
def get_money(self):
return self.__money
def set_money(self, n):
self.__money += n
经过修改,外部使用这个类的对象时,想使用对象中的属性,只能通过类中提供的 set/get 接口来操作,提高了程序的安全性。
这样,程序基本达到了设计需求,但是能不能更加完善呢?
如果在使用这个类的对象过程中,由于误操作,传入了不正常的数据,导致数据异常。该如何以避免这种情况发生呢?
比如:设置金额时出现了负数,或字符串,或其它类型的对象。
class Bank: def __init__(self, name, money): self.__name = name self.__money = money def get_name(self): return self.__name def get_money(self): return self.__money def set_money(self, n): if isinstance(n, int): if n > 0: self.__money = n else: raise ValueError('输入金额错误') else: raise ValueError('输入金额不是数字')
属性操作
在python中,提供了一个property类,通过对创建这个类的对象的设置,可以使用对象的私有属性时,可以不再使用函数的调用方式,而是相对普通的公有属性一样去使用属性,为开发者提供便利。
格式:
property(fget=None,fset=None,fdel=None,doc=None) #property attribute
property 是一个类,__init__方法由四个参数组成,实例后返回一个用来操作属性的对象
class Bank: def __init__(self, name, money): self.__name = name self.__money = money def __get_name(self): return self.__name def get_money(self): return self.__money def set_money(self, n): if isinstance(n, int): if n > 0: self.__money = n else: raise ValueError('输入金额错误') else: raise ValueError('输入金额不是数字') # 使用property类来为属性设置便利的访问方式 name = property(__get_name) money = property(get_money, set_money) ba = Bank('Tom', 10000) print(ba.name) print(ba.money) ba.money = 1000 print(ba.money) #输出 Tom 10000 1000
通过 property 类实例对象以后,在使用对象中的属性时,就可以像使用普通公有属性一样来调用,但是实际调用的还是 set/get 方法。 在实例 property 对象时,不是所有的参数都需要写,比如示例中的 name 只提供了 get 方法,并且是一个私有的方法。这样就完全隐藏了内部的实现细节 。
另一种写法。
class Bank: def __init__(self, name, money): self.__name = name self.__money = money @property def name(self): return self.__name @property def money(self): return self.__money @money.setter def money(self, n): if isinstance(n, int): if n > 0: self.__money = n else: raise ValueError('输入金额错误') else: raise ValueError('输入金额不是数字') ba = Bank('Tom', 10000) print(ba.name) print(ba.money) ba.money = 1000 print(ba.money) #输出 Tom 10000 1000
如果对象的方法中需要使用该对象的属性,该怎么办?
调用对象的方法时,为什么不需要设置self对应的参数?
class Cat:
# 方法
def introduce(self):
print('name is: %s,age is: %d' % (self.name, self.age))
cat = Cat()
cat.name = 'abc'
cat.age = 123
cat.introduce()
#输出
name is: abc,age is: 123
方法内定义属性
class Cat:
# 方法
def introduce(self):
self.type = '小型动物'
cat = Cat()
cat.introduce()
print(cat.type)
#输出
小型动物
创建对象时,系统会自动调用’_new_'方法。
开发者可以使用’_new_'方法自定义对象的创建过程。
__new__
至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
__new__
必须要有返回值,返回实例化出来的实例,这点在自己实现__new__
时要特别注意,可以return父类__new__
出来的实例,或者直接是object的__new__
出来的实例
__init__
有一个参数self,就是这个__new__
返回的实例,__init__
在__new__
的基础上可以完成一些其它初始化的动作,__init__
不需要返回值
如果创建对象时传递了自定义参数,且重写了new方法,则new也必须 “预留” 该形参,否则__init__方法将无法获取到该参数
class Cat: # 方法 def __new__(cls, name): print('创建对象') return object.__new__(cls) def __init__(self, name): print('对象初始化') self.name = name def __str__(self): return '%s' % self.name c = Cat('猫') print(c) #输出 猫
对象后面加括号,触发执行
构造方法的执行是有创建对象触发的,即:对象=类名()
而对于,’_call_'方法的执行是由对象后加括号出发的,即对象()或者类()
class A:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__called,print x:',*args, **kwargs)
a=A()
a('123')
#输出
__call__called,print x: 123
调用类的说明,这个属性无法继承给子类。
class Foo:
'''这是一段说明'''
pass
print(Foo.__doc__)
#输出
这是一段说明
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。