day15-2
成员
利用反射查看面向对象成员的归属
利用反射可以查看类里面方法
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. def aa(self):
6. print("AA")
7.
8.obj = foo("haha")
9.
10.r = hasattr(foo, "aa")
11.print(r)
上面的例子;利用__init__():创建对象的同时;将 name = “haha” 封装到obj对象里面去了
同样使用反射也可以查看对象里面的元素。
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. def aa(self):
6. print("AA")
7.
8.obj = foo("haha")
9.
10.r = hasattr(obj, "name")
11.print(r)
注意:
1、利用__init__():封装的对象是属于对象的
2、类里面的方法是属于类的。
问题:那能不能通过类创建的对象反射类里面的元素那?
答案也是可以的。
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. def aa(self):
6. print("AA")
7.
8.obj = foo("haha")
9.
10.r = hasattr(obj, "aa")
11.print(r)
总结:
通过对象即可以反射对象自身的元素;也可以反射类里面的元素
静态字段
1.class foo:
2. # 静态字段,属于类
3. country = "China"
4.
5. def __init__(self, name):
6. self.name = name
7.
8. def aa(self):
9. print("AA")
注意:静态字段属于类;存在类中
存在的意义
将每个对象里面;重复的东西;拿出来;在类里面保存一份就可以
没有静态字段:
1.class foo:
2. def __init__(self, name):
3. self.name = name
4. self.country = "中国"
5.
6. def aa(self):
7. print("AA")
8.
9.beijing = foo("北京")
10.shanghai = foo("上海")
分析:
上面的代码;每创建一个对象;里面都会封装一个固定的字段; country = “中国”;这样会显得重复;每个对象都有;都会保存一份
加上静态字段:
1. class foo:
2. # 静态字段,只在类中保存一次
3. country = "中国"
4. def __init__(self, name):
5. self.name = name
6.
7. def aa(self):
8. print("AA")
9.
10.beijing = foo("北京")
11.shanghai = foo("上海")
分析:
1、上面这样写;静态字段只会在类中保存一次;不用在每个对象中都保存。
2、同样;每个对象也可以获取这个静态字段
成员访问规则
自己的成员自己访问
以上面例子为例:
- 创建对象;后会被封装一个字段 name;而这个name 就的由 创建的对象去访问;如:beijing.name 或 shanghai.name
- 上面例子中 country 是类中;则由类自己访问;如:foo.country
说明:
在java和C#里面规则就是自己的成员自己访问;这是进行的扩展
但是,类中方法的除外
类中的方法在调用的时候要传递一个self;即对象本身;如果你用类去调用自己的方法;会导致self指向不明;
但是;可以先创建个对象;然后在类调用自己的方法的时候将对象传进去。– 这样做没什么意义
静态方法
@staticmethod
装饰类中的方法;通过staticmethod一装饰;类中的这个方法就变成了静态方法
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. # 将方法转换为静态方法
6. @staticmethod
7. def aa():
8. print("AA")
上面代码可以看出;静态方法和普通方法的区别;静态方法不用接收参数 self 而普通必须传
静态方法的调用:
类和对象都可以调用静态方法。
但是前面我们规定了;即静态方法最好由类自己调用
类方法
@classmethod
创建类方法
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. # 将方法转换为静态方法
6. @classmethod
7. def aa(cls):
8. print(cls)
9.
10.foo.aa()
结果显示:
1.<class '__main__.foo'>
从上面代码看出;类方法;必须接收一个参数 cls (class的缩写);这个参数是方法自动传入
注意:
1、cls:表示调用它的对象的类的名字(看显示结果)
2、类方法必须由类访问
3、类方法的 cls 会自动传进去的。
类方法接收参数:
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. # 将方法转换为静态方法
6. @classmethod
7. def aa(cls, name):
8. print(name)
9.
10.foo.aa("haha")
结果显示:
1.haha
特性
特点
特性:将方位伪造成字段
正常调用类中的普通方法
1.class foo:
2. def __init__(self, name):
3. self.name = name
4.
5. def aa(self):
6. print(self.name)
7.
8.r = foo("haha")
9.# 正常调用普通方法
10.r.aa()
使用属性中的特性:
1.class foo:
2. def __init__(self, name):
3. self.name = name
4. # 加上特性条件
5. @property
6. def aa(self):
7. print(self.name)
8.
9.r = foo("haha")
10.# 注意这里的调用方式
11.r.aa
分析:
从上面2段代码可以看出来。特性的特点就是在执行的时候;不用在方法后面加括号()
这就是所谓的伪造字段
问题:如果我们要传参数;而使用特性;结果怎样?
1.class foo:
2. def __init__(self, name):
3. self.name = name
4. # 加上特性条件
5. @property
6. def aa(self, e):
7. print(self.name)
8.
9.r = foo("haha")
10.# 注意这里的调用方式
11.r.aa
注意:
因为特性在执行的时候不用加括号();所以没办法加参数;所以特性不接收参数;上面的代码;会报错!
问题:我们知道在类中静态字段的调用也是可以由对象加字段名调用的;如果类里面有个静态字段的名字和特性名字相同;结果会怎样?
使用对象调用类中静态字段(这里违反前面的规定):
1.class foo:
2. aa = "AA"
3. def __init__(self, name):
4. self.name = name
5.
6.r = foo("haha")
7.
8.print(r.aa)
结果:
1.AA
代码中加上特性
1.class foo:
2. aa = "AA"
3. def __init__(self, name):
4. self.name = name
5.
6. @property
7. def aa(self):
8. print(self.name)
9.
10.r = foo("haha")
11.
12.print(r.aa)
输出结果:
1.haha
2.None
总结:
当类中有静态字段名字和特性方法的名字一样的时候;利用对象调用这个名字的时候;输出的是特性方法的结果;不会输出静态字段内容
特性修改值
特性是将方法伪造成字符段的;是不接收传值的
我们知道普通字段可以通过对象.字符名 = 值 来对值进行修改。
1.class foo:
2. aa = "AA"
3. def __init__(self, name):
4. self.name = name
5.
6.r = foo("haha")
7.print(r.name)
8.# 修改字段
9.r.name = "heihei"
10.print(r.name)
结果显示:
1.haha
2.heihei
问题:那特性能不能也这样直接修改值那?
答案:不行。会报错!
1.class foo:
2. aa = "AA"
3. def __init__(self, name):
4. self.name = name
5.
6. @property
7. def aa(self):
8. return self.name
9.r = foo("haha")
10.print(r.aa)
11.# 设置特性的值
12.r.aa = "heihei"
13.print(r.name)
结果显示:
1.haha
2.报错!
问题:那样怎么操作才能将普通字段的值设置那?
使用 @ xx.setter
- xx:表示特性方法的名字
1.class foo:
2. aa = "AA"
3. def __init__(self, name):
4. self.name = name
5.
6. @property
7. def aa(self):
8. return self.name
9. @aa.setter
10. def aa(self, value):
11. self.name = value
12.r = foo("haha")
13.print(r.name)
14.# 设置特性的值
15.r.aa = "heihei"
16.print(r.name)
显示结果:
1.haha
2.heihe
分析:
- 1、我们获取的时候;它会自动调@property下面的方法;
- 2、当我们传值的时候他会自动调用setter下面的方法
注意:
设置特性方法的时候 setter 前面的方法名、及setter下面设置方法的名字和设置时候方法的方法名;必须特性方法的方法名一样;不然会出错(可以看上面图片中对应相同的几个名字)
总结:
对象调用:有self参数的
- 普通方法
- 对象中的普通字段
- 特性
类调用的:无self参数的
- 静态字段
- 静态方法
- 类方法
浙公网安备 33010602011771号