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.nameshanghai.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

Alt text

分析:

  • 1、我们获取的时候;它会自动调@property下面的方法;
  • 2、当我们传值的时候他会自动调用setter下面的方法

注意:
设置特性方法的时候 setter 前面的方法名、及setter下面设置方法的名字和设置时候方法的方法名;必须特性方法的方法名一样;不然会出错(可以看上面图片中对应相同的几个名字)


总结:
对象调用:有self参数的

  • 普通方法
  • 对象中的普通字段
  • 特性

类调用的:无self参数的

  • 静态字段
  • 静态方法
  • 类方法

posted on 2016-10-30 00:27  jayafs  阅读(94)  评论(0)    收藏  举报

导航