{"id":4814,"date":"2015-05-25T16:15:38","date_gmt":"2015-05-25T13:15:38","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=4814"},"modified":"2015-05-21T06:05:46","modified_gmt":"2015-05-21T03:05:46","slug":"read-properties-python","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/","title":{"rendered":"Read-Only Properties in Python"},"content":{"rendered":"<p>Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in <code>property<\/code> descriptor\/decorator works very well for defining properties, but they have a small weakness in my eyes: it doesn\u2019t have defaults for simple usage.<\/p>\n<p>Yes, not supplying the property class with all methods does have the decent default of not allowing that usage, but I mean that it doesn\u2019t automatically implement some form of backing field. Backing fields are done completely explicitly by you.<\/p>\n<p>This is not a problem in some cases. In fact, it makes the property class exceptionally versatile, but at the cost of my explicitness on the part of the user. It has its uses, and it\u2019s great at them. But I have need for something a little less versatile, more specialized, and more implicit.<\/p>\n<p>I strongly try to make as many of my classes immutable as possible, avoiding side effects. Because of this, I want my class attributes to be read-only. There are two existing ways to deal with this. The first is to simply document that I want the attributes to be left alone. This is valid, and has a sort of simplicity to it, but sometimes I like to back up those intents with something a little more restrictive. The second option is to use a <code>property<\/code> without defining a setter. This is actually a very good option, but as I said while leading up to this, it\u2019s highly explicit. I want a property that is designed for the express purpose of being read-only.<\/p>\n<p>In this article, I present two different ideas that I\u2019ve had for \u201cread-only\u201d properties. I put read-only in quotes because, being properties, you still need to set the initial value. That part was the most difficult part, but I\u2019ve found two different ways to get around it. I call the two methods for doing so \u201cset once\u201d and \u201csecret set\u201d.<\/p>\n<p>Both methods have a simple lookup for the <code>__get__<\/code> implementation. You could do this one of two ways. When setting the value, you could store it back on the instance object with a backing field, or within the descriptor using a dict with the instance as the key.<\/p>\n<p>In general, I like the former method more, since it more accurately follows how other property mechanisms in other languages work. It can also speed up lookup if there is a large number of the objects, since there are less likely to be collisions within the small dict of an object than a large dict in a descriptor. It comes at a price, though.<\/p>\n<p>You either have to come up with a random backing field name and hope it doesn\u2019t clash with anything, or you can have the constructor take in an explicit name for the backing field. Lastly, the backing field is more easily discovered, since it\u2019s within the object\u2019s <code>__dict__<\/code>.<\/p>\n<p>In order to make the code simpler overall, the examples (and probably what I fully end up going with) will use an internal dict for the descriptor.<\/p>\n<h2><b>Set Once Property<\/b><\/h2>\n<p>The <code>SetOnceProperty<\/code> has what is probably the most obvious and direct route of implementation and is easier to use. It\u2019s a little less open to being set again if needed, but it fits most purposes. It\u2019s also <i>very<\/i> slightly less performant when setting the initial value. Not enough to even be noticeable unless you are doing it billions of time.<\/p>\n<p>The way it works is like this: When <code>__set__<\/code> is called with an instance, it checks to see if the instance already has a value set. If it does, it raises an <code>AttributeError<\/code> (with no message in this case, but that\u2019s just for brevity). If it doesn\u2019t have a value, it\u2019s set. That\u2019s all.<\/p>\n<p>If you REALLY need to change the value again, the <code>__get__<\/code> method returns the descriptor instance when called from the class instead of the instance. From there, you can access the dict and fiddle there. This will be the same in the <code>SecretSetProperty<\/code>, too, but it has a slightly cleaner way of changing it again.<\/p>\n<p>Here it is:<\/p>\n<pre class=\" brush:php\">class SetOnceProperty():\r\n    def __init__(self):\r\n        self.instances = {}\r\n\r\n    def __get__(self, instance, owner):\r\n        if instance is None:\r\n            return self\r\n        else:\r\n            return self.instances[instance]\r\n\r\n    def __set__(self, instance, value):\r\n        if instance in self.instances:\r\n            raise AttributeError\r\n        else:\r\n            self.instances[instance] = value<\/pre>\n<h2><b>Secret Set Property<\/b><\/h2>\n<p>I call it \u201csecret set\u201d because the way of setting the value to the property is done is a secret way. Generally, it\u2019s impossible to have direct access to a descriptor, since it\u2019s \u201cmagically\u201d accessed normally. You can override <code>__getattribute__<\/code> to change descriptor access, which I considered for a while, using a function that would monkeypatch the method, use the new one, then set the method back to how it previously was, but I try to avoid monkeypatching. Instead, like I did in the <code>SetOnceProperty<\/code>, I simply return the descriptor itself when it\u2019s accessed by class instead of instance.<\/p>\n<p>Why do I want to get the descriptor object? Because <code>SecretSetProperty<\/code> has a \u201csecret\u201d method, called <code>initialize<\/code>, for setting the property value. This way, the normal <code>__set__<\/code> call can always prevent the change by accident, but the value can still fairly easily be set at any time.<\/p>\n<p>Here\u2019s the code for it:<\/p>\n<pre class=\" brush:php\">class SecretSetProperty():\r\n    def __init__(self):\r\n        self.instances = {}\r\n\r\n    def __get__(self, instance, owner):\r\n        if instance is None:\r\n            return self\r\n        else:\r\n            return self.instances[instance]\r\n\r\n    def __set__(self, instance, value):\r\n        raise AttributeError\r\n\r\n    def initialize(self, instance, value):\r\n        self.instances[instance] = value<\/pre>\n<h2><b>Using the Properties<\/b><\/h2>\n<p>Okay, we have the properties, but I should make sure you guys know how to create them and set the values. Following, I have <code>SOPTest<\/code> and <code>SSPTest<\/code>. They are classes that each have a property named <code>prop<\/code>, and each use the <code>SetOnceProperty<\/code> and <code>SecretSetProperty<\/code>, respectively.<\/p>\n<pre class=\" brush:php\">class SOPTest():\r\n    prop = SetOnceProperty()\r\n\r\n    def __init__(self, val):\r\n        self.prop = val<\/pre>\n<pre class=\" brush:php\">\r\nclass SSPTest():\r\nprop = SecretSetProperty()\r\ndef __init__(self, val):\r\nSSPTest.prop.initialize(self, val)<\/pre>\n<h2><b>Outro<\/b><\/h2>\n<p>That\u2019s my proposal for some \u201cread-only\u201d property classes. What do you think? Are they worthwhile? Has anyone seen some made by someone else?<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/programmingideaswithjake.wordpress.com\/2015\/05\/16\/read-only-properties-in-python\/\">Read-Only Properties in Python<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Jacob Zimmerman at the <a href=\"http:\/\/programmingideaswithjake.wordpress.com\/\">Programming Ideas With Jake<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for defining properties, but they have a small weakness in my eyes: it doesn\u2019t have defaults for simple usage. Yes, not supplying the property class with all methods does have the decent default of not allowing that &hellip;<\/p>\n","protected":false},"author":51,"featured_media":1651,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[],"class_list":["post-4814","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Read-Only Properties in Python - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Read-Only Properties in Python - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-05-25T13:15:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jacob Zimmerman\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/jacobz_20\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jacob Zimmerman\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\"},\"author\":{\"name\":\"Jacob Zimmerman\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/f54a53cfb8523f4ef6012aa63f075c39\"},\"headline\":\"Read-Only Properties in Python\",\"datePublished\":\"2015-05-25T13:15:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\"},\"wordCount\":925,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"articleSection\":[\"Python\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\",\"name\":\"Read-Only Properties in Python - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"datePublished\":\"2015-05-25T13:15:38+00:00\",\"description\":\"Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/python\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Read-Only Properties in Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/f54a53cfb8523f4ef6012aa63f075c39\",\"name\":\"Jacob Zimmerman\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/2dfdd9e2d35ed2224faf73968f8c597b5489fc345287e06e2571d3935a6bcc86?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/2dfdd9e2d35ed2224faf73968f8c597b5489fc345287e06e2571d3935a6bcc86?s=96&d=mm&r=g\",\"caption\":\"Jacob Zimmerman\"},\"description\":\"Jacob is a certified Java programmer (level 1) and Python enthusiast. He loves to solve large problems with programming and considers himself pretty good at design.\",\"sameAs\":[\"https:\/\/programmingideaswithjake.wordpress.com\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/jacobz_20\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/jacob-zimmerman\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Read-Only Properties in Python - Web Code Geeks - 2026","description":"Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/","og_locale":"en_US","og_type":"article","og_title":"Read-Only Properties in Python - Web Code Geeks - 2026","og_description":"Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for","og_url":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-05-25T13:15:38+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","type":"image\/jpeg"}],"author":"Jacob Zimmerman","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/jacobz_20","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Jacob Zimmerman","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/"},"author":{"name":"Jacob Zimmerman","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/f54a53cfb8523f4ef6012aa63f075c39"},"headline":"Read-Only Properties in Python","datePublished":"2015-05-25T13:15:38+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/"},"wordCount":925,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","articleSection":["Python"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/","url":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/","name":"Read-Only Properties in Python - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","datePublished":"2015-05-25T13:15:38+00:00","description":"Python descriptors are a fairly powerful mechanic, especially for creating properties. The built-in property descriptor\/decorator works very well for","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/python\/read-properties-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Python","item":"https:\/\/www.webcodegeeks.com\/category\/python\/"},{"@type":"ListItem","position":3,"name":"Read-Only Properties in Python"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/f54a53cfb8523f4ef6012aa63f075c39","name":"Jacob Zimmerman","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/2dfdd9e2d35ed2224faf73968f8c597b5489fc345287e06e2571d3935a6bcc86?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/2dfdd9e2d35ed2224faf73968f8c597b5489fc345287e06e2571d3935a6bcc86?s=96&d=mm&r=g","caption":"Jacob Zimmerman"},"description":"Jacob is a certified Java programmer (level 1) and Python enthusiast. He loves to solve large problems with programming and considers himself pretty good at design.","sameAs":["https:\/\/programmingideaswithjake.wordpress.com\/","https:\/\/x.com\/https:\/\/twitter.com\/jacobz_20"],"url":"https:\/\/www.webcodegeeks.com\/author\/jacob-zimmerman\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/4814","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/51"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=4814"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/4814\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/1651"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=4814"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=4814"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=4814"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}