{"id":239,"date":"2010-03-27T22:40:43","date_gmt":"2010-03-28T03:40:43","guid":{"rendered":"http:\/\/www.insomnihack.com\/?p=239"},"modified":"2010-03-27T22:40:43","modified_gmt":"2010-03-28T03:40:43","slug":"traits","status":"publish","type":"post","link":"https:\/\/www.insomnihack.com\/?p=239","title":{"rendered":"Traits"},"content":{"rendered":"<p>I&#8217;m sure you&#8217;ve met the type. You mention some aspect of Python or Ruby or JavaScript that you really think is cool, and the other person reacts like you suggested they try the raw eel: an almost imperceptible shiver and a comment along the lines of &#8220;Yeah, but dynamic typing? Why not just fling poo at the monitor till your program&#8217;s done.&#8221;<\/p>\n<p><a href=\"http:\/\/www.insomnihack.com\/wp-content\/uploads\/static_typing_duh.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-241\" style=\"border: 2px solid black;\" title=\"Static Typing (Duh)\" src=\"http:\/\/www.insomnihack.com\/wp-content\/uploads\/static_typing_duh.jpg\" alt=\"\" width=\"354\" height=\"220\" srcset=\"https:\/\/www.insomnihack.com\/wp-content\/uploads\/static_typing_duh.jpg 354w, https:\/\/www.insomnihack.com\/wp-content\/uploads\/static_typing_duh-300x186.jpg 300w\" sizes=\"(max-width: 354px) 100vw, 354px\" \/><\/a><\/p>\n<p>Well at least in the case of Python, there&#8217;s another option those unhappy dogmatists who can&#8217;t bring themselves to leave the kiddie pool of strong typing: Traits.<\/p>\n<p>The <a href=\"http:\/\/code.enthought.com\/projects\/traits\/\">Traits<\/a> package from <a href=\"http:\/\/www.enthought.com\">Enthought<\/a> introduces a special kind of type definition called a trait to the Python language. As stated in the <a href=\"http:\/\/code.enthought.com\/projects\/traits\/docs\/html\/traits_user_manual\/index.html\">user manual<\/a>, a trait can be used for normal Python  object attributes, giving the attributes some additional characteristics:<\/p>\n<ul id=\"index-1031\">\n<li><strong>Initialization<\/strong>: A trait has a <em>default value<\/em>,  which is automatically set as the initial value of an attribute, before its first use in a program.<\/li>\n<\/ul>\n<ul id=\"index-1032\">\n<li><strong>Validation<\/strong>: A trait attribute is <em>explicitly  typed<\/em>. The type of a trait-based attribute is evident in the code, and only values that meet a programmer-specified set of criteria (i.e., the trait definition) can be assigned to that attribute. Note that the default value need not meet  the criteria defined for assignment of values. Traits 3.0 also supports  defining and using abstract interfaces, as well as adapters between interfaces.<\/li>\n<\/ul>\n<ul id=\"index-1033\">\n<li><strong>Deferral<\/strong>: The value of a trait attribute can be  contained either in the defining object or in another object that is <em>deferred to<\/em> by the trait.<\/li>\n<\/ul>\n<ul id=\"index-1034\">\n<li><strong>Notification<\/strong>: Setting the value of a trait  attribute can <em>notify<\/em> other parts of the program that the value has changed.<\/li>\n<\/ul>\n<ul id=\"index-1035\">\n<li><strong>Visualization<\/strong>: User interfaces that allow a user to  <em>interactively modify<\/em> the values of trait attributes can be automatically  constructed using the traits\u2019 definitions. This feature requires that a supported GUI toolkit be installed. However, if this feature is not used, the Traits  package does not otherwise require GUI support. For details on the visualization features of Traits, see the <a href=\"http:\/\/code.enthought.com\/projects\/traits\/docs\/html\/TUIUG\/index.html\"><em>Traits UI User Guide<\/em><\/a>.<\/li>\n<\/ul>\n<p>A class can freely mix trait-based attributes with normal Python  attributes, or can opt to allow the use of only a fixed or open set of trait  attributes within the class. Trait attributes defined by a class are automatically inherited by any subclass derived from the class.<\/p>\n<p>Using them is pretty easy, just extend your class from HasTraits.<\/p>\n<p>[python]<br \/>\nclass OldSchool(object):<br \/>\n    def __init__(self):<br \/>\n        # Man, I hope no one puts something other than a string in name!<br \/>\n        self.name = &#8221;<\/p>\n<p>from enthought.traits.api import HasTraits, String<\/p>\n<p>class NewHotness(HasTraits):<br \/>\n    # Just try setting name to an int, hippie!<br \/>\n    name = String()<br \/>\n[\/python]<\/p>\n<p>If you try to set a trait to any old type, you get a TraitError exception.<\/p>\n<p>[text]<br \/>\n&gt;&gt;&gt; from enthought.traits.api import HasTraits, String<br \/>\n&gt;&gt;&gt; class NewHotness(HasTraits):<br \/>\n&#8230;\u00a0\u00a0\u00a0\u00a0 name = String()<br \/>\n&#8230;<br \/>\n&gt;&gt;&gt; nh = NewHotness()<br \/>\n&gt;&gt;&gt; nh.name<br \/>\n&#8221;<br \/>\n&gt;&gt;&gt; nh.name = &#8216;A string&#8217;<br \/>\n&gt;&gt;&gt; nh.name<br \/>\n&#8216;A string&#8217;<br \/>\n&gt;&gt;&gt; nh.name = object()<br \/>\nTraceback (most recent call last):<br \/>\n  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;<br \/>\n  File &quot;C:\\Tools\\Python26\\lib\\site-packages\\enthought\\traits\\trait_types.py&quot;, line 720, in validate<br \/>\n    return getattr( self, self._validate )( object, name, value )<br \/>\n  File &quot;C:\\Tools\\Python26\\lib\\site-packages\\enthought\\traits\\trait_types.py&quot;, line 744, in validate_str<br \/>\n    self.error( object, name, value )<br \/>\n  File &quot;C:\\Tools\\Python26\\lib\\site-packages\\enthought\\traits\\trait_handlers.py&quot;, line 175, in error value )<br \/>\n    enthought.traits.trait_errors.TraitError: The &#8216;name&#8217; trait of a NewHotness instance must be a string, but a value of &lt;object object at 0x01D315F8&gt; &lt;type &#8216;object&#8217;&gt; was specified.<br \/>\n[\/text]<\/p>\n<p>The <a href=\"http:\/\/code.enthought.com\/projects\/traits\/docs\/html\/traits_user_manual\/defining.html#other-predefined-traits\">predefined traits<\/a> allow you to set maximum and minimum values, default values, as well support sensible type conversions. For example, if I set name to a float or an integer, the String trait will convert the value to a string.<\/p>\n<p>[python]<br \/>\n&gt;&gt;&gt; nh.name = 1.23<br \/>\n&gt;&gt;&gt; nh.name<br \/>\n&#8216;1.23&#8217;<br \/>\n[\/python]<\/p>\n<p>For the most part, traits are compatible with the other packages that make Python such a nice language to program in. For example, you can pickle classes that use traits or stuff them into an object database if you want.<\/p>\n<p>[python]<br \/>\ntry:<br \/>\n    from cPickle import loads, dumps<br \/>\nexcept:<br \/>\n    from pickle import loads, dumps<\/p>\n<p>from enthought.traits.api import HasTraits, String<br \/>\nfrom ZODB.FileStorage import FileStorage<br \/>\nfrom ZODB.DB import DB<\/p>\n<p>import transaction<\/p>\n<p>class MyClass(HasTraits):<br \/>\n    name = String()<\/p>\n<p>def test_pickle():<br \/>\n    m = MyClass()<br \/>\n    m.name = &#8216;Bob&#8217;<br \/>\n    p = dumps(m)<br \/>\n    n = loads(p)<br \/>\n    print &#8216;SAME:&#8217;, m is n<br \/>\n    print &#8216;EQUAL:&#8217;, m.name == n.name<br \/>\n    print &#8216;m.name =&#8217;, m.name<br \/>\n    print &#8216;n.name =&#8217;, n.name<\/p>\n<p>def test_write_zodb():<br \/>\n    storage = FileStorage(&#8216;TestData.fs&#8217;)<br \/>\n    db = DB(storage)<br \/>\n    connection = db.open()<br \/>\n    root = connection.root()<br \/>\n    m = MyClass()<br \/>\n    m.name = &#8216;Frank&#8217;<br \/>\n    root[&#8216;Frank&#8217;] = m<br \/>\n    transaction.commit()<br \/>\n    print root.keys()<br \/>\n    db.close()<\/p>\n<p>def test_read_zodb():<br \/>\n    storage = FileStorage(&#8216;TestData.fs&#8217;)<br \/>\n    db = DB(storage)<br \/>\n    connection = db.open()<br \/>\n    root = connection.root()<br \/>\n    m = root[&#8216;Frank&#8217;]<br \/>\n    print &quot;Name =&quot;, m.name<br \/>\n    db.close()<\/p>\n<p>if __name__ == &#8216;__main__&#8217;:<br \/>\n    test_pickle()<br \/>\n    test_write_zodb()<br \/>\n    test_read_zodb()<br \/>\n[\/python]<\/p>\n<p>Running the snippet above results in the following output:<\/p>\n<p>[text]<br \/>\nC:\\Tools\\Python26\\python.exe &quot;C:\/Tools\/Python\/TraitTests\/TraitTester.py&quot;<br \/>\nSAME: False<br \/>\nEQUAL: True<br \/>\nm.name = Bob<br \/>\nn.name = Bob<br \/>\n[&#8216;Frank&#8217;]<br \/>\nName = Frank<br \/>\n[\/text]<\/p>\n<p>There&#8217;s a lot more to traits than what I&#8217;ve described here. You can grab the package from <a href=\"http:\/\/pypi.python.org\/pypi\">PyPI<\/a> by downloading directly or via easy_install.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m sure you&#8217;ve met the type. You mention some aspect of Python or Ruby or JavaScript that you really think is cool, and the other person reacts like you suggested they try the raw eel: an almost imperceptible shiver and a comment along the lines of &#8220;Yeah, but dynamic typing? Why not just fling poo [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[6],"_links":{"self":[{"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=\/wp\/v2\/posts\/239"}],"collection":[{"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=239"}],"version-history":[{"count":0,"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=\/wp\/v2\/posts\/239\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=239"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=239"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.insomnihack.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=239"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}