C#基础系列 - 反射基础
反射用于在程序运行过程中,获取类里面的信息或发现程序集并运行的一个过程。通过反射可以获得.dll和.exe后缀的程序集里面的信息。使用反射可以看到一个程序集内部的类,接口,字段,属性,方法,特性等信息。
一、各种GetType()、typeof的区别
首先就是获取Tyoe对象的来源不同:
class Program
{
static void Main(string[] args)
{ Type t1 = Type.GetType("ConsoleApplication2.Person"); //从字符串中获得Type对象
Console.WriteLine(t1.ToString()); Type t2 = typeof(ConsoleApplication2.Person); //从具体类中获得Type对象
Console.WriteLine(t2.ToString()); Person p = new Person();
Type t3 = p.GetType(); //实例,从实例中获得Type对象 Assembly ass = Assembly.LoadFrom(@"C:\Users\Administrator\Desktop\ConsoleApplication2\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe");
Console.WriteLine(ass.GetType("ConsoleApplication2.Person").ToString()); //从字符串中获得Type对象
Module mod = ass.GetModules()[];
Console.WriteLine(mod.GetType("ConsoleApplication2.Person").ToString()); //从字符串中获得Type对象 Console.ReadKey();
}
}
三者的区别在于typeof()和Type.GetType()是从一个类中获取对象,而Object.GetType()是从一个类的实例获得对象。
而前两者的区别在于:
- 只有typeof()是运算符。
- Type.GetType()是实例方法。
- Object.GetType()是基类System.Object的方法(无参数,在Type类、Assembly类、Module类中都有这个无参方法),实例方法。
- Assembly.GetType() 、Module.GetType()、Type.Get()都是各自对象的实例方法。
在System.Reflection命名空间内包含多个反射常用的类,下面表格列出了常用的几个类。
类型 | 作用 |
Assembly | 通过此类可以加载操纵一个程序集,并获取程序集内部信息 |
EventInfo | 该类保存给定的事件信息 |
FieldInfo | 该类保存给定的字段信息 |
MethodInfo | 该类保存给定的方法信息 |
MemberInfo | 该类是一个基类,它定义了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多个公用行为 |
Module | 该类可以使你能访问多个程序集中的给定模块 |
ParameterInfo | 该类保存给定的参数信息 |
PropertyInfo | 该类保存给定的属性信息 |
二、System.Reflection.Assembly类
过Assembly可以动态加载程序集,并查看程序集的内部信息,其中最常用的就是Load()这个方法。
Assembly assembly = Assembly.Load("MyAssembly");
注意在Assembly里面的加载程序集有3个方法,分别是Load、LoadFrom和LoadFile。这3个方法有什么异同呢?
1、如果你引用了命名空间,那么就直接Load()方法,参数里面写上命名空间+类名就可以加载了。
2、如果仅仅知道一个dll文件的那么就要用LoadFrom()方法了,参数里面直接填写完整的路径。
LoadFrom 方法具有以下缺点。请考虑改用 Load。
-如果已加载一个具有相同标识的程序集,则即使指定了不同的路径,LoadFrom 仍返回已加载的程序集。
-如果用 LoadFrom 加载一个程序集,随后加载上下文中的一个程序集尝试加载具有相同显示名称的程序集,则加载尝试将失败。对程序集进行反序列化时,可能发生这种情况。
总结: LoadFrom只能用于加载不同标识的程序集, 也就是唯一的程序集, 不能用于加载标识相同但路径不同的程序集。
3、LoadFile (加载指定路径上的程序集文件的内容。)
这个方法是从指定的文件来加载程序集,它是调用外部的API实现的加载方式,和上面Load,LoadFrom方法的不同之处是这个方法不会加载此程序集引用的其他程序集,也就是不会加载程序的依赖项。而同时也是不能加载相同标识的程序集的。
利用Assembly的object CreateInstance(string)方法可以反射创建一个对象,参数0为类名。
class Program
{
static void Main(string[] args)
{
Assembly assm = Assembly.Load("fanshe");
Console.WriteLine(assm.FullName); //输出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //注释上面两行,移除程序集的引用 Assembly assm1 = Assembly.LoadFrom(@"D:\fanshe.dll");
Console.WriteLine(assm1.FullName); ////输出 fanshe, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null //与Assembly.LoadFrom基本一样,只是如果被加载的dll,还依赖其他的dll的话,被依赖的对象不会加载
Assembly assm2 = Assembly.LoadFile(@"D:\fanshe.dll");
Console.WriteLine(assm2.FullName); Console.ReadKey();
}
}
三、System.Type类
Type是最常用到的类,它一般用于装载反射得到的类对象,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可以得到Type对象。
1.利用typeof()得到Type对象
Type type = typeof(Example);
2.利用System.Object.GetType()得到Type对象
Example example = new Example();
Type type = example.GetType();
3.利用System.Type.GetType()得到Type对象
Type type = Type.GetType("MyAssembly.Example",false,true) //注意0是类名,参数1表示若找不到对应类时是否抛出异常,参数2表示类名是否区分大小写
示例:
public class Program
{
static void Main(string[] args)
{
Person p1 = new Person(); Type t1 = typeof(Person);
Type t2 = p1.GetType(); Person p2 = Activator.CreateInstance(t1) as Person;
Person p3 = Activator.CreateInstance(t2) as Person; Console.ReadKey();
}
} public class Person
{
public int Id { get; set; } public string Name { get; set; }
}
四、利用反射方法(Type.InvokeMember)获取或调用不同数据的对象、属性、方法
public object InvokeMember(string, BindingFlags, Binder, object, object[]);
string:你所要调用的函数名
BindingFlags:你所要调用的函数的属性,可以组合
Binder:高级内容,可以先不看
object:调用该成员函数的实例
object[]:参数,
例子:
举例:
Type tDate = typeof(System.DateTime);
Object result = tDate.InvokeMember("Now",
BindingFlags.GetProperty, null, null, new Object[]);
Console.WriteLine(result.ToString()); 例2: /*注意:下面备注的方法都是其他类的方法,比如:TestClass类方法*/
TestClass tc = new TestClass (); //AddUp为tc的方法
tc.GetType().InvokeMember ("AddUp", BindingFlags.Public |
BindingFlags.Instance | BindingFlags.CreateInstance,
null, tc, new object [] {});
/*
public void AddUp ()
{
methodCalled++;
Console.WriteLine ("AddUp Called {0} times", methodCalled);
}
*/
//----------------------------下面传参数 执行ComputeSum方法 带有两个参数
Type t = typeof (TestClass);
object [] args = new object [] {100.09, 184.45};
object result = t.InvokeMember ("ComputeSum", BindingFlags.InvokeMethod, null, null, args);
/*
public static double ComputeSum (double d1, double d2)
{
return d1 + d2;
}
*/
//-----------SayHello为静态方法调用
t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object [] {});
//-----------实例方法调用
TestClass c = new TestClass ();
c.GetType().InvokeMember ("AddUp", BindingFlags.InvokeMethod, null, c, new object [] {}); c.GetType().InvokeMember ("AddUp", BindingFlags.Public |
BindingFlags.Instance | BindingFlags.CreateInstance,
null, c, new object [] {}); //----------获取字段
result = t.InvokeMember ("Name", BindingFlags.GetField | BindingFlags.GetProperty, null, c, new object [] {});
result = t.InvokeMember ("Value", BindingFlags.GetField | BindingFlags.GetProperty, null, c, new object [] {});
/*
public String Name;
public Object Value
{
get
{
return "the value";
}
}
*/
result = t.InvokeMember ("Name", BindingFlags.GetField, null, c, new object [] {});
//---------设置字段
t.InvokeMember ("Name", BindingFlags.SetField, null, c, new object [] {"NewName"}); //NewName设置的属性值
//---------调用类方法 带参数
object[] argValues = new object [] {"Mouse", "Micky"};
String [] argNames = new String [] {"lastName", "firstName"};
t.InvokeMember ("PrintName", BindingFlags.InvokeMethod, null, null, argValues, null, null, argNames);
/*
public static void PrintName (String firstName, String lastName)
{
Console.WriteLine ("{0},{1}", lastName,firstName);
}
*/
TestClass obj = new TestClass();
System.Reflection.MethodInfo methInfo =
obj.GetType().GetMethod("PrintName");
methInfo.Invoke(obj,BindingFlags.SuppressChangeType |
BindingFlags.InvokeMethod, null,new object[]
{"Brad","Smith"},null); methInfo = obj.GetType().GetMethod("PrintName");
methInfo.Invoke(obj,BindingFlags.IgnoreCase | //忽略大小写 指定当绑定时不应考虑成员名的大小写
BindingFlags.InvokeMethod, null,new object[]
{"brad","smith"},null); methInfo = obj.GetType().GetMethod("PrintName");
methInfo.Invoke(obj,BindingFlags.IgnoreReturn | // 在 COM interop 中用于指定可以忽略成员的返回值
BindingFlags.InvokeMethod, null,new object[]
{"Brad","Smith"},null); methInfo = obj.GetType().GetMethod("PrintName");
methInfo.Invoke(obj,BindingFlags.OptionalParamBinding |
BindingFlags.InvokeMethod, null,new object[]
{"Brad","Smith"},null); // BindingFlags.ExactBinding
methInfo = obj.GetType().GetMethod("PrintName");
methInfo.Invoke(obj,BindingFlags.ExactBinding |
BindingFlags.InvokeMethod, null,new object[]
{"Brad","Smith"},null); // BindingFlags.FlattenHierarchy
methInfo = obj.GetType().GetMethod("PrintName");
methInfo.Invoke(obj,BindingFlags.FlattenHierarchy |
BindingFlags.InvokeMethod, null,new object[]
{"Brad","Smith"},null);
//----------调用一个默认的方法
Type t3 = typeof (TestClass2);
/*
[DefaultMemberAttribute ("PrintTime")]
public class TestClass2
{
public void PrintTime ()
{
Console.WriteLine (DateTime.Now);
}
}
*/
t3.InvokeMember ("", BindingFlags.InvokeMethod | BindingFlags.Default, null, new TestClass2(), new object [] {});
//---------调用一个引用方法
MethodInfo m = t.GetMethod("Swap");
args = new object[];
args[] = ;
args[] = ;
m.Invoke(new TestClass(),args);
/*
public void Swap(ref int a, ref int b) 交换 a b
{
int x = a;
a = b;
b = x;
}
*/
利用反射创建对象还可以用以下方法:
Assembly assembly = Assembly.Load("fanshe");
Type type = assembly.GetType("fanshe.Person"); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type);
四、反射方法
1.通过 Type.GetMethods()能查找到类里面的方法
代码示例:
class Program
{
static void Main(string[] args)
{
Type t = typeof(Person);
MethodInfo[] MethodInfoList = t.GetMethods();
foreach (MethodInfo info in MethodInfoList)
{
Console.WriteLine(info);
} Console.ReadKey();
}
}
输出结果如下:
留意到里面所有的方法,包括继承来的都列出来了。另外可以留意到,属性的读取设置,在根本上也是一个方法。
调用反射得到的方法使用Invoke方法(),示例如下:
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("fanshe");
Type type = assembly.GetType("fanshe.Person"); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type);
MethodInfo methodShow = type.GetMethod("Show"); //根据方法名获取MethodInfo对象
//调用无参方法Show,Invoke表示执行方法
methodShow.Invoke(obj, null); // 参数1类型为object[],代表Hello World方法的对应参数,输入值为null代表没有参数
// methodShow.Invoke(obj,new object[]{parm1, ref parm2,.....}); 若方法带参数,用new object进行赋值传进去
Console.ReadKey();
}
五、反射属性
1、通过System.Reflection.Property能查找到类里面的属性
常用的方法有GetValue(object,object[])获取属性值和SetValue(object,object,object[])设置属性值
代码示例:
class Program
{
static void Main(string[] args)
{
Type t = typeof(Person);
PropertyInfo[] PropertyInfoList = t.GetProperties();
foreach (PropertyInfo info in PropertyInfoList)
{
Console.WriteLine(info);
} Console.ReadKey();
}
}
输出结果如下:
2、另外还可以通过PropertyInfo对象的GetValue和SetValue方法读取和设置创建出来的对象的属性值
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("fanshe");
Type type = assembly.GetType("fanshe.Person"); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type); //调用要属性的方法
PropertyInfo propertyName = type.GetProperty("Name"); //获取Name属性对象
propertyName.SetValue(obj, "张飞", null); //设置Name属性的值 object objName = propertyName.GetValue(obj, null); //获取属性值
Console.WriteLine(objName); //输出张飞 Console.ReadKey();
}
}
下面给出一个方法与属性的综合示例:
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("fanshe");
Type type = assembly.GetType("fanshe.Person"); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type);
MethodInfo methodShow = type.GetMethod("Show"); //根据方法名获取MethodInfo对象
//调用无参方法Show,Invoke表示执行方法
methodShow.Invoke(obj, null); // 参数1类型为object[],代表Hello World方法的对应参数,输入值为null代表没有参数 //调用带参数方法
MethodInfo methodAdd = type.GetMethod("Add");
object[] objArr = new object[]{,};
methodAdd.Invoke(obj,objArr); //输出3 第二个参数为传入去的参数列表 //调用要属性的方法
PropertyInfo propertyName = type.GetProperty("Name"); //获取Name属性对象
propertyName.SetValue(obj,"张飞",null); //设置Name属性的值
PropertyInfo propertyAge = type.GetProperty("Age"); //获取Age属性对象
propertyAge.SetValue(obj, , null); //把Age属性设置为34
MethodInfo methodSay = type.GetMethod("Say");
methodSay.Invoke(obj,null); //输出我的名字叫张飞,我今年24岁 Console.ReadKey();
}
}
Person类的代码如下:
namespace fanshe
{
public class Person
{
private string name;
public string Name get { return name; } set { name = value; } } private int age;
public int Age { get { return age; } set { age = value; } } public void Show() { Console.WriteLine("我是Person类里的Show方法!"); } public void Say() { Console.WriteLine("我的名字叫{0},我今年{1}岁", this.Name, this.Age); } public void Add(int i, int j) { Console.WriteLine(i + j); }
}
}
2、根据属性的类型设置属性的值:
我们有可能会一次过设置很多属性的值,而这些属性里面可能有字符串类型、整型等等。因此,我们需要动态设置,这是需要根据属性的类型设置属性的值。
namespace DynamicSetValue
{
class Program
{
static void Main(string[] args)
{
Type type = typeof(Person); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type);
//假设这是存在于XML的数据
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("Id", "");
dic.Add("Name", "神灵武士");
dic.Add("Birthday", "2001-01-01"); PropertyInfo[] ProArr = type.GetProperties();
foreach (PropertyInfo p in ProArr)
{
if (dic.Keys.Contains(p.Name))
{
p.SetValue(obj, Convert.ChangeType(dic[p.Name], p.PropertyType), null); //当需要给属性设置不同类型的值时
}
} Person person = obj as Person;
Console.WriteLine(person.Birthday); Console.ReadKey();
}
} //有三种不同类型的属性
public class Person
{
public int Id { get; set; }
public string Name { get; set;}
public DateTime Birthday { get; set; }
}
}
输出如下:
如果不根据类型来转换,则报如下错误:
六、反射字段
通过 System.Reflection.FieldInfo 能查找到类里面的字段
它包括有两个常用方法SetValue(object ,object )和GetValue(object) 因为使用方法与反射属性非常相似。
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("fanshe");
Type type = assembly.GetType("fanshe.Person"); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type); //调用要属性的方法
FieldInfo fieldName = type.GetField("name", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public | BindingFlags.Instance); //获取name字段对象,后面的那个枚举参数指定,非公开字段也搜索,即读取private的name字段
fieldName.SetValue(obj, "张飞"); //设置name字段的值 object objName = fieldName.GetValue(obj); //获取属性值
Console.WriteLine(objName); //输出张飞 Console.ReadKey();
}
}
七、反射特性
通过System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一个类里面的特性。
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("fanshe");
Type type = assembly.GetType("fanshe.Person"); //注意要输入全部路径,包括命名空间
object obj = Activator.CreateInstance(type);
object[] typeAttributes=type.GetCustomAttributes(false); //获取Person类的特性
foreach (object attribute in typeAttributes)
{
Console.WriteLine(attribute.ToString()); //输出 System.SerializableAttribute 因为我在Person上里加了个[Serializable]
} Console.ReadKey();
}
}
八、应用实例
利用反射实现的简单工厂模式的多数据库系统实例:
App.Config配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DAL" value="ConsoleApplication2.Access"/>
</appSettings>
</configuration>
主程序代码:
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("ConsoleApplication2");
string str = System.Configuration.ConfigurationManager.AppSettings["DAL"];
Type type = assembly.GetType(str); //注意真正实现的对象路径写在了外面,这样要更改数据库只要改配置文件,不需要改动程序!
IDAL DAL = (IDAL)Activator.CreateInstance(type);
DAL.Insert(); Console.ReadKey();
}
} interface IDAL
{
void Insert();
} class SqlServer : IDAL
{
public void Insert()
{
Console.WriteLine("SqlServer增加一条记录!");
}
} class Access : IDAL
{
public void Insert()
{
Console.WriteLine("Access增加一条记录!");
}
}
}
2、不引用命名空间根据路径运行dll里的方法示例
Person类代码:
namespace fanshe
{
public class Person
{
private string name;
public string Name
{ get { return name; } { name = value; } } private int age;
public int Age
{ get { return age; } set { age = value; } } public string Say(string str)
{
Console.WriteLine("我的名字叫{0},我今年{1}岁,另外你给我传入的参数是:{2}", this.Name, this.Age,str);
return "返回结果";
}
}
}
主程序代码:
class Program
{
static void Main(string[] args)
{
//先把引用的命名空间移除
Assembly assembly = Assembly.LoadFrom(@"D:\fanshe.dll");
Type type = assembly.GetType("fanshe.Person");
object obj = Activator.CreateInstance(type);
PropertyInfo proName = type.GetProperty("Name");
proName.SetValue(obj,"关羽",null);
PropertyInfo proAge = type.GetProperty("Age");
proAge.SetValue(obj,,null);
MethodInfo methodSay = type.GetMethod("Say");
object[] objList = new object[]{"传入测试参数"};
object result = methodSay.Invoke(obj,objList);
Console.WriteLine(result); //输出 返回值 Console.ReadKey();
}
}
3、获得List<T>中的T类型:
List<Dog> dogs = new List<Dog>();
Type type = dogs.GetType();
if (type.IsGenericType)
{
Type[] genericArgTypes = type.GetGenericArguments();
if (genericArgTypes[] == typeof(Dog))
{
//你想要判断的是这个吗?
}
}
当然,如果List<T>是你定义的泛型,那么直接typeof(T)更加简单。
C#基础系列 - 反射基础的更多相关文章
- C#基础系列-反射
1.反射的定义 反射(Reflection),是.Net中获取运行时类型信息的方式.程序集中有关程序及其类型的数据被称为元数据(metadata).程序在运行时,可以查看其它程序集或其本身的元数据.一 ...
- C#基础系列——反射笔记
前言:使用反射也有几年了,但是一直觉得,反这个概念很抽象,今天有时间就来总结下这个知识点. 1.为什么需要反射: 最初使用反射的时候,作为小菜总是不理解,既然可以通过new 一个对象的方式得到对象,然 ...
- Java基础系列--01_基础类型
J2SE.J2ME.J2EE分别指什么? J2SE 基础版,桌面应用. J2ME 微型版,手机开发.(android,ios) J2EE 企业版,所有浏览器访问的应用程序. 注意:JDK5以后改名 J ...
- C#基础系列——Attribute特性使用
前言:上篇 C#基础系列——反射笔记 总结了下反射得基础用法,这章我们来看看C#的另一个基础技术——特性. 1.什么是特性:就博主的理解,特性就是在类的类名称.属性.方法等上面加一个标记,使这些类.属 ...
- C#基础系列——小话泛型
前言:前面两章介绍了C#的两个常用技术:C#基础系列——反射笔记 和 C#基础系列——Attribute特性使用 .这一章来总结下C#泛型技术的使用.据博主的使用经历,觉得泛型也是为了重用而生的,并且 ...
- C#基础系列——委托和设计模式(二)
前言:前篇 C#基础系列——委托实现简单设计模式 简单介绍了下委托的定义及简单用法.这篇打算从设计模式的角度去解析下委托的使用.我们知道使用委托可以实现对象行为(方法)的动态绑定,从而提高设计的灵活性 ...
- C#基础系列——再也不用担心面试官问我“事件”了
前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类...你是否也曾经被问到过?你又是否都答出来了呢? ...
- C#基础系列——异步编程初探:async和await
前言:前面有篇从应用层面上面介绍了下多线程的几种用法,有博友就说到了async, await等新语法.确实,没有异步的多线程是单调的.乏味的,async和await是出现在C#5.0之后,它的出现给了 ...
- C#基础系列——一场风花雪月的邂逅:接口和抽象类
前言:最近一个认识的朋友准备转行做编程,看他自己边看视频边学习,挺有干劲的.那天他问我接口和抽象类这两个东西,他说,既然它们如此相像, 我用抽象类就能解决的问题,又整个接口出来干嘛,这不是误导初学者吗 ...
随机推荐
- 安装mysql-5.6版本步骤与卸载
官网下载完解压后: 1.环境变量配置Path D:\mysql-5.6.40-winx64\bin(你的mySql5.6的路径到bin)2.找到D:\mysql-5.6.40-winx64文件中的 ...
- lower_bound/upper_bound example
http://www.cplusplus.com/reference/algorithm/upper_bound/左闭右开 Return iterator to lower bound Returns ...
- Nginx Upstream Keepalive 分析 保持长连接
Nginx Upstream长连接由upstream模式下的keepalive指令控制,并指定可用于长连接的连接数,配置样例如下: upstream http_backend { server ...
- P3942 将军令
P3942 将军令 梦里,小 F 成了一个给将军送密信的信使. 现在,有两封关乎国家生死的密信需要送到前线大将军帐下,路途凶险,时间紧迫.小 F 不因为自己的祸福而避趋之,勇敢地承担了这个任务. 不过 ...
- 自动化工具制作PASCAL VOC 数据集
自动化工具制作PASCAL VOC 数据集 1. VOC的格式 VOC主要有三个重要的文件夹:Annotations.ImageSets和JPEGImages JPEGImages 文件夹 该文件 ...
- Java基础-IO流对象之File类
Java基础-IO流对象之File类 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.IO技术概述 回想之前写过的程序,数据都是在内存中,一旦程序运行结束,这些数据都没有了,等下 ...
- Java基础-正则表达式(Regular Expression)语法规则简介
Java基础-正则表达式(Regular Expression)语法规则简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.正则表达式的概念 正则表达式(Regular Exp ...
- 科学计算三维可视化---Mayavi入门(Mayavi介绍和安装)
Mayavi介绍 是基于VTK开发的可视化软件(更加高效),Mayavi完全由python编写,方便使用,而且可以使用python编写扩展,嵌入到用户程序中 安装要求 VTK >pip3 ins ...
- Ubuntu16.04.2安装Tensorflow
安装aptitude $ sudo apt-get install aptitude 安装python-pip python-dev $ sudo aptitude install python-pi ...
- Spyder docstrings文档字符串的标准
Spyder docstrings文档字符串的规范 python的docstring 非常重要. 有时候编写一个小函数只需要几行代码就可了. 但是完善的文档很可能比源代码长许多. 特点和标准 docs ...