Python:面向对象编程(类、类属性)

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

类的创建:

class Student(object):  # 类名一般大写

	def __init__(self, name, score):  #  注意:特殊方法“__init__”前后分别有两个下划线!!!
	    self.name = name
	    self.score = score
	    
	def print_score(self):
	    print('%s %s' % (self.name, self.score))
    
s1 = Student('wangxuan', 90)
s1.print_score()
print(type(s1))  # 类型是student类
print(s1)  # <__main__.Student object at 0x105c07ad0>是一个类的实例

在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__ ,在Python中,实例的变量名如果以__ 开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

class Student(object):
	def __init__(self, name, score):
	    self.__name = name
	    self.__score = score
	
	def print_score(self):
	    print('%s: %s' % (self.__name, self.__score))

但是如果外部代码要获取name和score怎么办?可以给Student类增加get_name和get_score这样的方法

class Student(object):

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

如果又要允许外部代码修改score怎么办?可以再给Student类增加set_score方法

class Student(object):
	
	def set_score(self, score):
	    self.__score = score

在方法中,可以对参数做检查,避免传入无效的参数

class Student(object):

	def set_score(self, score):
	    if 0 <= score <= 100:
	        self.__score = score
	    else:
	        raise ValueError('bad score')

变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量
变量名类似_name的,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”
变量名类似__name的,一般不能从外部访问,不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量

>>> bart._Student__name
'Bart Simpson'

但是强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名

类属性:

所有实例都拥有

class Student(object):
    count = 0  # 类属性

    def __init__(self, name):
        self.name = name
        Student.count += 1  # 每次调用则加一,统计注册学生的数量

动态给类绑定实例和方法:

动态给实例绑定一个属性

s.name = 'zhangsan'
print(s.name)

# 动态给实例绑定一个方法(只有当前实例可以使用)
def set_age(self, age):  # 定义一个函数作为实例方法
    self.age = age

from types import MethodType
s.set_age = MethodType(set_age, s)  # 给实例绑定方法
s.set_age(20)  # 调用实例方法
print(s.age)  # 打印

# 动态给类添加方法
# 给类添加方法后所有的实例都可以使用了
Student.set_age = MethodType(set_age, Student)  
s2 = Student()
s2.set_age(25)
print(s2.age)

s3 = Student()
s3.set_age(30)
print(s3.age)

上面的set_age方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。

限制实例的属性:( __ slots __ )

# 限制实例属性
class Student(object):
    __slots__ = ('name', 'age')  # 限制只能添加name和age

s1 = Student()
s1.name = 'zhangsan'
s1.age = 30
# s1.score = 90  # 添加不进去
try:
    s1.score = 99
except AttributeError as e:
    print('AttributeError:', e)

由于’score’没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。
使用__slots__要注意,__ slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。

你可能感兴趣的:(Python,python)